1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
// Tests that class member function calls do not prevent devirtualization (vtable cannot change in class member call).
// RUN: %ldc -output-ll -of=%t.ll %s -O3 && FileCheck %s < %t.ll
class A {
void foo();
final void oof();
}
class B : A {
override void foo();
}
// CHECK-LABEL: define{{.*}}ggg
void ggg()
{
A a = new A();
// CHECK: call {{.*}}_D29devirtualization_assumevtable1A3foo
a.foo();
// CHECK: call {{.*}}_D29devirtualization_assumevtable1A3foo
a.foo();
}
// CHECK-LABEL: define{{.*}}hhh
void hhh()
{
A a = new A();
// CHECK: call {{.*}}_D29devirtualization_assumevtable1A3oof
a.oof();
// CHECK: call {{.*}}_D29devirtualization_assumevtable1A3foo
a.foo();
}
// CHECK-LABEL: define{{.*}}directcall
void directcall()
{
A a = new A();
// CHECK: call {{.*}}_D29devirtualization_assumevtable1A3foo
a.A.foo();
// CHECK: call {{.*}}_D29devirtualization_assumevtable1A3foo
a.foo();
}
// CHECK-LABEL: define{{.*}}exacttypeunknown
void exacttypeunknown(A a, A b)
{
// CHECK: %[[FOO:[0-9a-z]+]] = load {{.*}}!invariant
// CHECK: call{{.*}} void %[[FOO]](
a.foo();
// CHECK: call{{.*}} void %[[FOO]](
a.foo();
a = b;
// CHECK: %[[FOO2:[0-9a-z]+]] = load {{.*}}!invariant
// CHECK: call{{.*}} void %[[FOO2]](
a.foo();
}
// No vtable loading and assume calls for struct method calls.
struct S {
void foo();
}
// CHECK-LABEL: define{{.*}}structS
void structS(S s)
{
// CHECK-NOT: llvm.assume
// CHECK-NOT: load
s.foo();
// CHECK: ret void
}
// The devirtualization is not valid for C++ methods.
extern(C++)
class CPPClass {
void foo();
void oof();
}
// CHECK-LABEL: define{{.*}}exactCPPtypeunknown
void exactCPPtypeunknown(CPPClass a)
{
// CHECK: %[[FOO:[0-9a-z]+]] = load {{.*}}!invariant
// CHECK: call{{.*}} void %[[FOO]](
a.foo();
// CHECK: %[[FOO2:[0-9a-z]+]] = load {{.*}}!invariant
// CHECK: call{{.*}} void %[[FOO2]](
a.foo();
}
|