[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
Wed Sep 15 14:00:42 PDT 2021


kubamracek updated this revision to Diff 372796.

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,9 +15,9 @@
 !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 trunc (i64 sub (i64 0, i64 ptrtoint (void ()* @weird_ref_2 to i64)) to i32)
+; CHECK-SAME:   i32 0,
+; CHECK-SAME:   i32 0,
+; CHECK-SAME:   i32 0
 ; CHECK-SAME: ] }, align 8, !type !0, !type !1, !vcall_visibility !2
 
 define internal void @vfunc1() { ret void }
Index: llvm/lib/Transforms/IPO/GlobalDCE.cpp
===================================================================
--- llvm/lib/Transforms/IPO/GlobalDCE.cpp
+++ llvm/lib/Transforms/IPO/GlobalDCE.cpp
@@ -416,6 +416,29 @@
       // 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.
+      for (auto *U : F->users()) {
+        if (auto *PtrExpr = dyn_cast<ConstantExpr>(U)) {
+          if (PtrExpr->getOpcode() == Instruction::PtrToInt) {
+            assert(PtrExpr->hasOneUser());
+            if (auto *SubExpr = dyn_cast<ConstantExpr>(PtrExpr->user_back())) {
+              assert(SubExpr->hasOneUser());
+              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.372796.patch
Type: text/x-patch
Size: 4175 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210915/dbe2a96f/attachment.bin>


More information about the llvm-commits mailing list