; Test that unreachable functions are ignored by WPD in hybrid LTO, and thin LTO. ; In this test case, the unreachable function is the virtual deleting destructor of an abstract class. ; Generate split module with summary for hybrid Regular LTO WPD ; RUN: opt -thinlto-bc -thinlto-split-lto-unit %s -o %t-main.bc ; RUN: opt -thinlto-bc -thinlto-split-lto-unit %p/Inputs/devirt_after_filtering_unreachable_lib.ll -o %t-foo.bc ; Check that deleting destructor of pure virtual class is unreachable. ; Check that deleting destructor of pure virtual class is unreachable. ; RUN: llvm-modextract -b -n=0 %t-foo.bc -o %t-foo.bc.0 ; RUN: llvm-dis -o - %t-foo.bc.0 | FileCheck %s --check-prefix=UNREACHABLEFLAG ; Tests that devirtualization happens. ; RUN: llvm-lto2 run -save-temps %t-main.bc %t-foo.bc -pass-remarks=. -o %t \ ; RUN: -whole-program-visibility \ ; RUN: -r=%t-foo.bc,_Z3fooP4Base,pl \ ; RUN: -r=%t-foo.bc,_ZN7DerivedD0Ev,pl \ ; RUN: -r=%t-foo.bc,_ZN4BaseD0Ev,pl \ ; RUN: -r=%t-foo.bc,_ZTV7Derived,l \ ; RUN: -r=%t-foo.bc,_ZTV4Base,l \ ; RUN: -r=%t-foo.bc,_ZN7DerivedD0Ev, \ ; RUN: -r=%t-foo.bc,_ZN4BaseD0Ev, \ ; RUN: -r=%t-foo.bc,_ZTV7Derived,pl \ ; RUN: -r=%t-foo.bc,_ZTV4Base,pl \ ; RUN: -r=%t-main.bc,main,plx \ ; RUN: -r=%t-main.bc,_Znwm,pl \ ; RUN: -r=%t-main.bc,_Z3fooP4Base, \ ; RUN: -r=%t-main.bc,_ZTV7Derived, 2>&1 | FileCheck %s --check-prefix=REMARK ; REMARK-COUNT-1: single-impl: devirtualized a call to _ZN7DerivedD0Ev ; Generate unsplit module with summary for ThinLTO index-based WPD. ; RUN: opt -thinlto-bc -o %t3.o %s ; Check that deleting destructor of pure virtual class is unreachable. ; RUN: opt -thinlto-bc -o %t4.o %p/Inputs/devirt_after_filtering_unreachable_lib.ll ; RUN: llvm-dis -o - %t4.o | FileCheck %s --check-prefix=UNREACHABLEFLAG ; UNREACHABLEFLAG: gv: (name: "_ZN4BaseD0Ev", {{.*}}, funcFlags: ({{.*}} mustBeUnreachable: 1 ; Test that devirtualized happen in index based WPD ; RUN: llvm-lto2 run %t4.o %t3.o -save-temps -pass-remarks=. \ ; RUN: -whole-program-visibility \ ; RUN: -wholeprogramdevirt-print-index-based \ ; RUN: -o %t5 \ ; RUN: -r=%t4.o,_Z3fooP4Base,pl \ ; RUN: -r=%t4.o,_ZN7DerivedD0Ev,pl \ ; RUN: -r=%t4.o,_ZN4BaseD0Ev,pl \ ; RUN: -r=%t4.o,_ZTV7Derived,pl \ ; RUN: -r=%t4.o,_ZTV4Base,pl \ ; RUN: -r=%t3.o,main,plx \ ; RUN: -r=%t3.o,_Znwm, \ ; RUN: -r=%t3.o,_Z3fooP4Base, \ ; RUN: -r=%t3.o,_ZTV7Derived, 2>&1 | FileCheck %s --check-prefix=THINREMARK ; THINREMARK: Devirtualized call to {{.*}} (_ZN7DerivedD0Ev) ; THINREMARK: single-impl: devirtualized a call to _ZN7DerivedD0Ev ; THINREMARK: single-impl: devirtualized a call to _ZN7DerivedD0Ev ; ModuleID = 'tmp.cc' source_filename = "tmp.cc" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" %Derived = type { %Base } %Base = type { i32 (...)** } @_ZTV7Derived = external constant { [5 x i8*] } define hidden i32 @main() { entry: %call = tail call i8* @_Znwm(i64 8) %0 = bitcast i8* %call to %Derived* %1 = getelementptr inbounds %Derived, %Derived* %0, i64 0, i32 0, i32 0 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTV7Derived, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %1 %2 = getelementptr %Derived, %Derived* %0, i64 0, i32 0 tail call void @_Z3fooP4Base(%Base* nonnull %2) ret i32 0 } declare i8* @_Znwm(i64) declare void @_Z3fooP4Base(%Base*)