Permalink
Browse files

[sil-devirtuaizer] Devirtualize super_method instructions.

SR-96 / rdar://23792487
  • Loading branch information...
swiftix committed Dec 7, 2015
1 parent d00ec3a commit 42fac944e3d12038dfb195ab544cae95ea0ce138
@@ -274,10 +274,10 @@ bool swift::canDevirtualizeClassMethod(FullApplySite AI,
// either be a metatype or an alloc_ref.
DEBUG(llvm::dbgs() << " Origin Type: " << ClassOrMetatypeType);

auto *CMI = cast<ClassMethodInst>(AI.getCallee());
auto *MI = cast<MethodInst>(AI.getCallee());

// Find the implementation of the member which should be invoked.
auto *F = getTargetClassMethod(Mod, ClassOrMetatypeType, CMI->getMember());
auto *F = getTargetClassMethod(Mod, ClassOrMetatypeType, MI->getMember());

// If we do not find any such function, we have no function to devirtualize
// to... so bail.
@@ -351,9 +351,9 @@ DevirtualizationResult swift::devirtualizeClassMethod(FullApplySite AI,
DEBUG(llvm::dbgs() << " Trying to devirtualize : " << *AI.getInstruction());

SILModule &Mod = AI.getModule();
auto *CMI = cast<ClassMethodInst>(AI.getCallee());
auto *MI = cast<MethodInst>(AI.getCallee());
auto ClassOrMetatypeType = ClassOrMetatype.getType();
auto *F = getTargetClassMethod(Mod, ClassOrMetatypeType, CMI->getMember());
auto *F = getTargetClassMethod(Mod, ClassOrMetatypeType, MI->getMember());

CanSILFunctionType GenCalleeType = F->getLoweredFunctionType();

@@ -654,5 +654,15 @@ DevirtualizationResult swift::tryDevirtualizeApply(FullApplySite AI) {
return tryDevirtualizeClassMethod(AI, Instance);
}

if (isa<SuperMethodInst>(AI.getCallee())) {
if (AI.hasSelfArgument()) {
return tryDevirtualizeClassMethod(AI, AI.getSelfArgument());
}

// It is an invocation of a class method.
// Last operand is the metatype that should be used for dispatching.
return tryDevirtualizeClassMethod(AI, AI.getArguments().back());
}

return std::make_pair(nullptr, FullApplySite());
}
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -emit-sil -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -use-native-super-method | FileCheck %s
// RUN: %target-swift-frontend -emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -use-native-super-method | FileCheck %s
class Parent {
func onlyInParent() {}
@@ -0,0 +1,30 @@
// RUN: %target-swift-frontend -emit-sil %s -use-native-super-method | FileCheck %s
class Parent {
@inline(never)
class func onlyInParent() {}
@inline(never)
final class func finalOnlyInParent() {}
@inline(never)
class func foo() {}
}

class Child : Parent {}

class Grandchild : Child {
class func onlyInGrandchild() {
// CHECK-LABEL: sil hidden @_TZFC18super_class_method10Grandchild16onlyInGrandchildfT_T_
// CHECK-NOT: super_method %0 : $@thick Grandchild.Type, #Parent.onlyInParent!1 : Parent.Type -> () -> () , $@convention(thin) (@thick Parent.Type) -> () // user: %5
// CHECK: function_ref @_TZFC18super_class_method6Parent12onlyInParentfT_T_
super.onlyInParent()
// CHECK: function_ref @_TZFC18super_class_method6Parent17finalOnlyInParentfT_T_
super.finalOnlyInParent()
}

override class func foo() {
// CHECK: sil hidden @_TZFC18super_class_method10Grandchild3foofT_T_ : $@convention(thin) (@thick Grandchild.Type) -> () {
// CHECK-NOT: super_method %0 : $@thick Grandchild.Type, #Parent.foo!1 : Parent.Type -> () -> () , $@convention(thin) (@thick Parent.Type) -> ()
// CHECK: function_ref @_TZFC18super_class_method6Parent3foofT_T_
super.foo()
}
}
@@ -0,0 +1,79 @@
// RUN: %target-swift-frontend -use-native-super-method -emit-sil %s | FileCheck %s
// CHECK-LABEL: sil hidden [noinline] @_TFC10super_init3FooCfSiS0_ : $@convention(thin) (Int, @thick Foo.Type) -> @owned Foo
// CHECK-NOT: class_method
// CHECK-NOT: super_method
// CHECK: [[SUPER_INIT:%.*]] = function_ref @_TFC10super_init3FoocfSiS0_
// CHECK: [[NEW_SELF:%.*]] = apply [[SUPER_INIT]]
// CHECK-LABEL: sil hidden [noinline] @_TFC10super_init3Barc
// CHECK-NOT: super_method [[ORIG_SELF]] : $Bar, #Foo.init!initializer.1
// CHECK: function_ref @_TFC10super_init3FoocfT_S0_
class Foo {
@inline(never)
init() {}
@inline(never)
init(_ x: Foo) {}
@inline(never)
init(_ x: Int) {}
}

class Bar: Foo {
@inline(never)
override init() {
super.init()
}
}

extension Foo {
@inline(never)
convenience init(x: Int) {
self.init()
}
}

class Zim: Foo {
var foo = Foo()
// CHECK-LABEL: sil hidden @_TFC10super_init3Zimc
// CHECK-NOT: super_method {{%[0-9]+}} : $Zim, #Foo.init!initializer.1
// CHECK: function_ref @_TFC10super_init3FooCfT_S0_
// CHECK: function_ref @_TFC10super_init3FoocfT_S0_
}

class Zang: Foo {
var foo: Foo

@inline(never)
override init() {
foo = Foo()
super.init()
}
// CHECK-LABEL: sil hidden [noinline] @_TFC10super_init4ZangcfT_S0_
// CHECK-NOT: super_method {{%[0-9]+}} : $Zang, #Foo.init!initializer.1
// CHECK: function_ref @_TFC10super_init3FooCfT_S0_
// CHECK: function_ref @_TFC10super_init3FoocfT_S0_
}

class Bad: Foo {
// Invalid code, but it's not diagnosed till DI. We at least shouldn't
// crash on it.
@inline(never)
override init() {
super.init(self)
}
}

class Good: Foo {
let x: Int

// CHECK-LABEL: sil hidden [noinline] @_TFC10super_init4GoodcfT_S0_
// CHECK-NOT: super_method {{%[0-9]+}} : $Good, #Foo.init!initializer.1
// CHECK: [[SUPER_INIT:%.*]] = function_ref @_TFC10super_init3FoocfSiS0_
// CHECK: apply [[SUPER_INIT]]
@inline(never)
override init() {
x = 10
super.init(x)
}
}
@@ -0,0 +1,30 @@
// RUN: %target-swift-frontend -emit-sil %s -use-native-super-method | FileCheck %s
class Parent {
@inline(never)
func onlyInParent() {}
@inline(never)
final func finalOnlyInParent() {}
@inline(never)
func foo() {}
}

class Child : Parent {}

class Grandchild : Child {
// CHECK: sil hidden @_TFC12super_method10Grandchild16onlyInGrandchildfT_T_
func onlyInGrandchild() {
// CHECK-NOT: super_method %0 : $Grandchild, #Parent.onlyInParent!1 : Parent -> () -> ()
// CHECK: function_ref @_TFC12super_method6Parent12onlyInParentfT_T_
super.onlyInParent()
// CHECK: function_ref @_TFC12super_method6Parent17finalOnlyInParentfT_T_
super.finalOnlyInParent()
}

// CHECK: sil hidden @_TFC12super_method10Grandchild3foofT_T_
override func foo() {
// CHECK-NOT: super_method %0 : $Grandchild, #Parent.foo!1 : Parent -> () -> ()
// CHECK: function_ref @_TFC12super_method6Parent3foofT_T_
super.foo()
}
}
@@ -0,0 +1,14 @@
// RUN: %target-swift-frontend -emit-sil %s -use-native-super-method | FileCheck %s
// RN: %target-swift-frontend -emit-sil -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -use-native-super-method | FileCheck %s
// REQUIRES: objc_interop
import Foundation
class MyFunkyDictionary: NSDictionary {
// CHECK-LABEL: sil hidden @_TZFC23super_objc_class_method17MyFunkyDictionary10initializefT_T_
// CHECK: super_method [volatile] %0 : $@thick MyFunkyDictionary.Type, #NSObject.initialize!1.foreign : NSObject.Type -> () -> ()
override class func initialize() {
super.initialize()
}
}

0 comments on commit 42fac94

Please sign in to comment.