[llvm] 6b53ad2 - [GlobalDCE] [VFE] Avoid dropping vfunc dependencies when an invalid vtable entry is present

Kuba Mracek via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 17 19:43:22 PST 2022


Author: Kuba Mracek
Date: 2022-02-17T19:41:46-08:00
New Revision: 6b53ad298e95a9f1cb5770dcbaa71cb4ea343021

URL: https://github.com/llvm/llvm-project/commit/6b53ad298e95a9f1cb5770dcbaa71cb4ea343021
DIFF: https://github.com/llvm/llvm-project/commit/6b53ad298e95a9f1cb5770dcbaa71cb4ea343021.diff

LOG: [GlobalDCE] [VFE] Avoid dropping vfunc dependencies when an invalid vtable entry is present

When we scan vtables for a particular vload in ScanVTableLoad and an entry in
one possible vtable is invalid (null or non-fptr), we bail in a wrong way -- we
completely stop the scanning of vtables and this results in dropped dependencies
and incorrectly removed vfuncs from vtables. Let's fix that by correcting the
bailing logic to keep iterating and only skip the invalid entries.

Differential Revision: https://reviews.llvm.org/D120006

Added: 
    llvm/test/Transforms/GlobalDCE/virtual-functions-nonptr.ll

Modified: 
    llvm/lib/Transforms/IPO/GlobalDCE.cpp
    llvm/test/Transforms/GlobalDCE/virtual-functions-null.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/GlobalDCE.cpp b/llvm/lib/Transforms/IPO/GlobalDCE.cpp
index e375504099610..79bf97b293bcc 100644
--- a/llvm/lib/Transforms/IPO/GlobalDCE.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalDCE.cpp
@@ -214,14 +214,14 @@ void GlobalDCEPass::ScanVTableLoad(Function *Caller, Metadata *TypeId,
     if (!Ptr) {
       LLVM_DEBUG(dbgs() << "can't find pointer in vtable!\n");
       VFESafeVTables.erase(VTable);
-      return;
+      continue;
     }
 
     auto Callee = dyn_cast<Function>(Ptr->stripPointerCasts());
     if (!Callee) {
       LLVM_DEBUG(dbgs() << "vtable entry is not function pointer!\n");
       VFESafeVTables.erase(VTable);
-      return;
+      continue;
     }
 
     LLVM_DEBUG(dbgs() << "vfunc dep " << Caller->getName() << " -> "

diff  --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-nonptr.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-nonptr.ll
new file mode 100644
index 0000000000000..695a0b55327f5
--- /dev/null
+++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-nonptr.ll
@@ -0,0 +1,44 @@
+; RUN: opt < %s -globaldce -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata)
+
+ at vtableA = internal unnamed_addr constant { [2 x i32] } { [2 x i32] [
+  i32 0,
+  i32 trunc (i64 sub (i64 ptrtoint (void ()* @vfunc2 to i64), i64 ptrtoint ({ [2 x i32] }* @vtableA to i64)) to i32)
+]}, align 8, !type !{i64 0, !"vfunc1.type"}, !type !{i64 4, !"vfunc2.type"}, !vcall_visibility !{i64 2}
+
+; CHECK:      @vtableA = internal unnamed_addr constant { [2 x i32] } { [2 x i32] [
+; CHECK-SAME:   i32 0,
+; CHECK-SAME:   i32 trunc (i64 sub (i64 ptrtoint (void ()* @vfunc2 to i64), i64 ptrtoint ({ [2 x i32] }* @vtableA to i64)) to i32)
+; CHECK-SAME: ] }, align 8
+
+ at vtableB = internal unnamed_addr constant { [2 x i32] } { [2 x i32] [
+  i32 trunc (i64 sub (i64 ptrtoint (void ()* @vfunc1 to i64), i64 ptrtoint ({ [2 x i32] }* @vtableB to i64)) to i32),
+  i32 trunc (i64 sub (i64 ptrtoint (void ()* @vfunc2 to i64), i64 ptrtoint ({ [2 x i32] }* @vtableB to i64)) to i32)
+]}, align 8, !type !{i64 0, !"vfunc1.type"}, !type !{i64 4, !"vfunc2.type"}, !vcall_visibility !{i64 2}
+
+; CHECK:      @vtableB = internal unnamed_addr constant { [2 x i32] } { [2 x i32] [
+; CHECK-SAME:   i32 trunc (i64 sub (i64 ptrtoint (void ()* @vfunc1 to i64), i64 ptrtoint ({ [2 x i32] }* @vtableB to i64)) to i32),
+; CHECK-SAME:   i32 trunc (i64 sub (i64 ptrtoint (void ()* @vfunc2 to i64), i64 ptrtoint ({ [2 x i32] }* @vtableB to i64)) to i32)
+; CHECK-SAME: ] }, align 8
+
+define internal void @vfunc1() {
+  ret void
+}
+
+define internal void @vfunc2() {
+  ret void
+}
+
+define void @main() {
+  %1 = ptrtoint { [2 x i32] }* @vtableA to i64 ; to keep @vtableA alive
+  %2 = ptrtoint { [2 x i32] }* @vtableB to i64 ; to keep @vtableB alive
+  %3 = tail call { i8*, i1 } @llvm.type.checked.load(i8* null, i32 0, metadata !"vfunc1.type")
+  %4 = tail call { i8*, i1 } @llvm.type.checked.load(i8* null, i32 0, metadata !"vfunc2.type")
+  ret void
+}
+
+!999 = !{i32 1, !"Virtual Function Elim", i32 1}
+!llvm.module.flags = !{!999}

diff  --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-null.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-null.ll
index 33be6451fa3f7..186967b6311ad 100644
--- a/llvm/test/Transforms/GlobalDCE/virtual-functions-null.ll
+++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-null.ll
@@ -20,7 +20,7 @@ declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata)
 ]}, align 8, !type !{i64 0, !"vfunc1.type"}, !type !{i64 8, !"vfunc2.type"}, !vcall_visibility !{i64 2}
 
 ; CHECK:      @vtableB = internal unnamed_addr constant { [2 x i8*] } { [2 x i8*] [
-; CHECK-SAME:   i8* null,
+; CHECK-SAME:   i8* bitcast (void ()* @vfunc1 to i8*),
 ; CHECK-SAME:   i8* bitcast (void ()* @vfunc2 to i8*)
 ; CHECK-SAME: ] }, align 8
 


        


More information about the llvm-commits mailing list