[PATCH] D109114: [GlobalDCE] In VFE, replace the whole 'sub' expression of unused relative-pointer-based vtable slots

Kuba (Brecka) Mracek via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 13 16:33:38 PDT 2021


kubamracek updated this revision to Diff 372365.
kubamracek retitled this revision from "[GlobalDCE] Add a mode to VFE that replaces unused vtable slots with a trap function instead of a NULL pointer" to "[GlobalDCE] In VFE, replace the whole 'sub' expression of unused relative-pointer-based vtable slots".
kubamracek added a comment.

Changing the title to reflect the change in direction of this patch.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109114/new/

https://reviews.llvm.org/D109114

Files:
  llvm/lib/Transforms/IPO/GlobalDCE.cpp
  llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-bad.ll
  llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-gep.ll
  llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers.ll


Index: llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers.ll
+++ llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers.ll
@@ -14,7 +14,7 @@
 
 ; CHECK:      @vtable = internal unnamed_addr constant { [2 x i32] } { [2 x i32] [
 ; CHECK-SAME:   i32 trunc (i64 sub (i64 ptrtoint (void ()* @vfunc1_live              to i64), i64 ptrtoint ({ [2 x i32] }* @vtable to i64)) to i32),
-; CHECK-SAME:   i32 trunc (i64 sub (i64 0,                                                    i64 ptrtoint ({ [2 x i32] }* @vtable to i64)) to i32)
+; CHECK-SAME:   i32 0
 ; CHECK-SAME: ] }, align 8, !type !0, !type !1, !vcall_visibility !2
 
 ; (1) vfunc1_live is referenced from @main, stays alive
Index: llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-gep.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-gep.ll
+++ llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-gep.ll
@@ -16,7 +16,7 @@
 
 ; CHECK:      @vtable = internal unnamed_addr constant { [4 x i32] } { [4 x i32] [
 ; CHECK-SAME:   i32 trunc (i64 sub (i64 ptrtoint (void ()* @vfunc1_live              to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @vtable, i32 0, i32 0, i32 2) to i64)) to i32),
-; CHECK-SAME:   i32 trunc (i64 sub (i64 0,                                                    i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @vtable, i32 0, i32 0, i32 2) to i64)) to i32)
+; CHECK-SAME:   i32 0
 ; CHECK-SAME: ] }, align 8, !type !0, !type !1, !vcall_visibility !2
 
 ; (1) vfunc1_live is referenced from @main, stays alive
Index: llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-bad.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-bad.ll
+++ llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-bad.ll
@@ -15,8 +15,8 @@
 !1 = !{i64 4, !"vfunc2.type"}
 
 ; CHECK:      @vtable = internal unnamed_addr constant { [3 x i32] } { [3 x i32] [
-; CHECK-SAME:   i32 trunc (i64 sub (i64 0, i64 ptrtoint ({ [3 x i32] }* @vtable to i64)) to i32),
-; CHECK-SAME:   i32 trunc (i64 sub (i64 0, i64 ptrtoint ({ [3 x i32] }* @vtable to i64)) to i32),
+; CHECK-SAME:   i32 0,
+; CHECK-SAME:   i32 0,
 ; CHECK-SAME:   i32 trunc (i64 sub (i64 ptrtoint (void ()* @weird_ref_1 to i64), i64 ptrtoint (void ()* @weird_ref_2 to i64)) to i32)
 ; CHECK-SAME: ] }, align 8, !type !0, !type !1, !vcall_visibility !2
 
Index: llvm/lib/Transforms/IPO/GlobalDCE.cpp
===================================================================
--- llvm/lib/Transforms/IPO/GlobalDCE.cpp
+++ llvm/lib/Transforms/IPO/GlobalDCE.cpp
@@ -440,6 +440,27 @@
       // virtual function pointers with null, allowing us to remove the
       // function itself.
       ++NumVFuncs;
+
+      // Detect vfuncs that are referenced as "relative pointers" which are used
+      // in Swift vtables, i.e. entries in the form of:
+      //
+      //   i32 trunc (i64 sub (i64 ptrtoint @f, i64 ptrtoint ...)) to i32)
+      //
+      // In this case, replace the whole "sub" expression with constant 0 to
+      // avoid leaving a weird sub(0, symbol) expression behind.
+      if (auto *PtrExpr = dyn_cast<ConstantExpr>(F->user_back())) {
+        if (PtrExpr->getOpcode() == Instruction::PtrToInt) {
+          assert(F->hasOneUser());
+          assert(PtrExpr->hasOneUser());
+          if (auto *SubExpr = dyn_cast<ConstantExpr>(PtrExpr->user_back())) {
+            if (SubExpr->getOpcode() == Instruction::Sub) {
+              SubExpr->replaceNonMetadataUsesWith(
+                  ConstantInt::get(SubExpr->getType(), 0));
+            }
+          }
+        }
+      }
+
       F->replaceNonMetadataUsesWith(ConstantPointerNull::get(F->getType()));
     }
     EraseUnusedGlobalValue(F);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D109114.372365.patch
Type: text/x-patch
Size: 4081 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210913/fb65f8d4/attachment.bin>


More information about the llvm-commits mailing list