Index: lib/Transforms/IPO/WholeProgramDevirt.cpp =================================================================== --- lib/Transforms/IPO/WholeProgramDevirt.cpp +++ lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -35,6 +35,7 @@ #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" @@ -610,6 +611,16 @@ return true; } +static void emitTargetsRemarks(const std::vector &TargetsForSlot) { + for (const VirtualCallTarget &Target : TargetsForSlot) { + Function *F = Target.Fn; + DISubprogram *SP = F->getSubprogram(); + DebugLoc DL = SP ? DebugLoc::get(SP->getScopeLine(), 0, SP) : DebugLoc(); + emitOptimizationRemark(F->getContext(), DEBUG_TYPE, *F, DL, + std::string("devirtualized ") + F->getName().str()); + } +} + void DevirtModule::rebuildGlobal(VTableBits &B) { if (B.Before.Bytes.empty() && B.After.Bytes.empty()) return; @@ -815,10 +826,15 @@ S.first.ByteOffset)) continue; - if (trySingleImplDevirt(TargetsForSlot, S.second)) + if (trySingleImplDevirt(TargetsForSlot, S.second)) { + emitTargetsRemarks(TargetsForSlot); continue; + } - DidVirtualConstProp |= tryVirtualConstProp(TargetsForSlot, S.second); + if (tryVirtualConstProp(TargetsForSlot, S.second)) { + emitTargetsRemarks(TargetsForSlot); + DidVirtualConstProp = true; + } } // If we were able to eliminate all unsafe uses for a type checked load, Index: test/Transforms/WholeProgramDevirt/devirt-single-impl.ll =================================================================== --- test/Transforms/WholeProgramDevirt/devirt-single-impl.ll +++ test/Transforms/WholeProgramDevirt/devirt-single-impl.ll @@ -1,8 +1,12 @@ -; RUN: opt -S -wholeprogramdevirt %s | FileCheck %s +; RUN: opt -S -wholeprogramdevirt -pass-remarks=wholeprogramdevirt %s 2>&1 | FileCheck %s target datalayout = "e-p:64:64" target triple = "x86_64-unknown-linux-gnu" +; CHECK: remark: :0:0: devirtualized call +; CHECK: remark: :0:0: devirtualized vf +; CHECK: remark: :0:0: devirtualized vf + @vt1 = constant [1 x i8*] [i8* bitcast (void (i8*)* @vf to i8*)], !type !0 @vt2 = constant [1 x i8*] [i8* bitcast (void (i8*)* @vf to i8*)], !type !0 Index: test/Transforms/WholeProgramDevirt/virtual-const-prop-check.ll =================================================================== --- test/Transforms/WholeProgramDevirt/virtual-const-prop-check.ll +++ test/Transforms/WholeProgramDevirt/virtual-const-prop-check.ll @@ -4,8 +4,20 @@ target triple = "x86_64-unknown-linux-gnu" ; CHECK: remark: :0:0: devirtualized call +; CHECK: remark: :0:0: devirtualized vf1i32 +; CHECK: remark: :0:0: devirtualized vf2i32 +; CHECK: remark: :0:0: devirtualized vf3i32 +; CHECK: remark: :0:0: devirtualized vf4i32 ; CHECK: remark: :0:0: devirtualized call +; CHECK: remark: :0:0: devirtualized vf1i1 +; CHECK: remark: :0:0: devirtualized vf0i1 +; CHECK: remark: :0:0: devirtualized vf1i1 +; CHECK: remark: :0:0: devirtualized vf0i1 ; CHECK: remark: :0:0: devirtualized call +; CHECK: remark: :0:0: devirtualized vf0i1 +; CHECK: remark: :0:0: devirtualized vf1i1 +; CHECK: remark: :0:0: devirtualized vf0i1 +; CHECK: remark: :0:0: devirtualized vf1i1 ; CHECK-NOT: devirtualized call ; CHECK: [[VT1DATA:@[^ ]*]] = private constant { [8 x i8], [3 x i8*], [0 x i8] } { [8 x i8] c"\00\00\00\01\01\00\00\00", [3 x i8*] [i8* bitcast (i1 (i8*)* @vf0i1 to i8*), i8* bitcast (i1 (i8*)* @vf1i1 to i8*), i8* bitcast (i32 (i8*)* @vf1i32 to i8*)], [0 x i8] zeroinitializer }, section "vt1sec", !type [[T8:![0-9]+]]