From: Piotr Padlewski Date: Sat, 29 Oct 2016 15:28:30 +0000 (+0000) Subject: [Devirtualization] Decorate vfunction load with invariant.load X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0578a8eedce5784b9791c8f95690ddcfb6d95a1d;p=clang [Devirtualization] Decorate vfunction load with invariant.load Summary: This patch was introduced one year ago, but because my google account was disabled, I didn't get email with failing buildbot and I missed revert of this commit. There was small but in test regex. I am back. Reviewers: rsmith, rengolin Subscribers: nlewycky, rjmccall, cfe-commits Differential Revision: https://reviews.llvm.org/D26117 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@285497 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index b8dec54a4e..29261fd4b3 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -1623,7 +1623,22 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, llvm::Value *VFuncPtr = CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn"); - VFunc = CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); + auto *VFuncLoad = + CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); + + // Add !invariant.load md to virtual function load to indicate that + // function didn't change inside vtable. + // It's safe to add it without -fstrict-vtable-pointers, but it would not + // help in devirtualization because it will only matter if we will have 2 + // the same virtual function loads from the same vtable load, which won't + // happen without enabled devirtualization with -fstrict-vtable-pointers. + if (CGM.getCodeGenOpts().OptimizationLevel > 0 && + CGM.getCodeGenOpts().StrictVTablePointers) + VFuncLoad->setMetadata( + llvm::LLVMContext::MD_invariant_load, + llvm::MDNode::get(CGM.getLLVMContext(), + llvm::ArrayRef())); + VFunc = VFuncLoad; } CGCallee Callee(MethodDecl, VFunc); diff --git a/test/CodeGenCXX/virtual-function-calls.cpp b/test/CodeGenCXX/virtual-function-calls.cpp index 0a6fc6b3f2..22944d94ca 100644 --- a/test/CodeGenCXX/virtual-function-calls.cpp +++ b/test/CodeGenCXX/virtual-function-calls.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - -fstrict-vtable-pointers -O1 | FileCheck --check-prefix=CHECK-INVARIANT %s // PR5021 namespace PR5021 { @@ -42,10 +43,14 @@ namespace VirtualNoreturn { [[noreturn]] virtual void f(); }; - // CHECK: @_ZN15VirtualNoreturn1f + // CHECK-LABEL: @_ZN15VirtualNoreturn1f + // CHECK-INVARIANT-LABEL: define void @_ZN15VirtualNoreturn1f void f(A *p) { p->f(); // CHECK: call {{.*}}void %{{[^#]*$}} // CHECK-NOT: unreachable + // CHECK-INVARIANT: load {{.*}} !invariant.load ![[EMPTY_NODE:[0-9]+]] } } + +// CHECK-INVARIANT: ![[EMPTY_NODE]] = !{}