[llvm] 7329abf - [GlobalDCE] In VFE, replace the whole 'sub' expression of unused relative-pointer-based vtable slots
Kuba Mracek via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 6 15:56:08 PDT 2021
Author: Kuba Mracek
Date: 2021-10-06T15:55:55-07:00
New Revision: 7329abf2f81a0432bd0a9e7dec0c55b692fc72e5
URL: https://github.com/llvm/llvm-project/commit/7329abf2f81a0432bd0a9e7dec0c55b692fc72e5
DIFF: https://github.com/llvm/llvm-project/commit/7329abf2f81a0432bd0a9e7dec0c55b692fc72e5.diff
LOG: [GlobalDCE] In VFE, replace the whole 'sub' expression of unused relative-pointer-based vtable slots
Differential Revision: https://reviews.llvm.org/D109114
Added:
llvm/test/Transforms/GlobalDCE/call-with-ptrtoint.ll
Modified:
llvm/include/llvm/Analysis/TypeMetadataUtils.h
llvm/lib/Analysis/TypeMetadataUtils.cpp
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
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/TypeMetadataUtils.h b/llvm/include/llvm/Analysis/TypeMetadataUtils.h
index 6ca112457b6f..074c40942b06 100644
--- a/llvm/include/llvm/Analysis/TypeMetadataUtils.h
+++ b/llvm/include/llvm/Analysis/TypeMetadataUtils.h
@@ -22,6 +22,7 @@ namespace llvm {
class CallBase;
class CallInst;
class Constant;
+class Function;
class DominatorTree;
class Instruction;
class Module;
@@ -56,25 +57,30 @@ void findDevirtualizableCallsForTypeCheckedLoad(
SmallVectorImpl<Instruction *> &Preds, bool &HasNonCallUses,
const CallInst *CI, DominatorTree &DT);
-// Processes a Constant recursively looking into elements of arrays, structs and
-// expressions to find a trivial pointer element that is located at the given
-// offset (relative to the beginning of the whole outer Constant).
-//
-// Used for example from GlobalDCE to find an entry in a C++ vtable that matches
-// a vcall offset.
-//
-// To support Swift vtables, getPointerAtOffset can see through "relative
-// pointers", i.e. (sub-)expressions of the form of:
-//
-// @symbol = ... {
-// i32 trunc (i64 sub (
-// i64 ptrtoint (<type> @target to i64), i64 ptrtoint (... @symbol to i64)
-// ) to i32)
-// }
-//
-// For such (sub-)expressions, getPointerAtOffset returns the @target pointer.
+/// Processes a Constant recursively looking into elements of arrays, structs
+/// and expressions to find a trivial pointer element that is located at the
+/// given offset (relative to the beginning of the whole outer Constant).
+///
+/// Used for example from GlobalDCE to find an entry in a C++ vtable that
+/// matches a vcall offset.
+///
+/// To support Swift vtables, getPointerAtOffset can see through "relative
+/// pointers", i.e. (sub-)expressions of the form of:
+///
+/// @symbol = ... {
+/// i32 trunc (i64 sub (
+/// i64 ptrtoint (<type> @target to i64), i64 ptrtoint (... @symbol to i64)
+/// ) to i32)
+/// }
+///
+/// For such (sub-)expressions, getPointerAtOffset returns the @target pointer.
Constant *getPointerAtOffset(Constant *I, uint64_t Offset, Module &M,
Constant *TopLevelGlobal = nullptr);
-}
+
+/// Finds the same "relative pointer" pattern as described above, where the
+/// target is `F`, and replaces the entire pattern with a constant zero.
+void replaceRelativePointerUsersWithZero(Function *F);
+
+} // namespace llvm
#endif
diff --git a/llvm/lib/Analysis/TypeMetadataUtils.cpp b/llvm/lib/Analysis/TypeMetadataUtils.cpp
index 65fa2bbcffd3..80051fd5f7c1 100644
--- a/llvm/lib/Analysis/TypeMetadataUtils.cpp
+++ b/llvm/lib/Analysis/TypeMetadataUtils.cpp
@@ -197,3 +197,20 @@ Constant *llvm::getPointerAtOffset(Constant *I, uint64_t Offset, Module &M,
}
return nullptr;
}
+
+void llvm::replaceRelativePointerUsersWithZero(Function *F) {
+ for (auto *U : F->users()) {
+ auto *PtrExpr = dyn_cast<ConstantExpr>(U);
+ if (!PtrExpr || PtrExpr->getOpcode() != Instruction::PtrToInt)
+ continue;
+
+ for (auto *PtrToIntUser : PtrExpr->users()) {
+ auto *SubExpr = dyn_cast<ConstantExpr>(PtrToIntUser);
+ if (!SubExpr || SubExpr->getOpcode() != Instruction::Sub)
+ continue;
+
+ SubExpr->replaceNonMetadataUsesWith(
+ ConstantInt::get(SubExpr->getType(), 0));
+ }
+ }
+}
diff --git a/llvm/lib/Transforms/IPO/GlobalDCE.cpp b/llvm/lib/Transforms/IPO/GlobalDCE.cpp
index 018a594127f0..9977fa7904a0 100644
--- a/llvm/lib/Transforms/IPO/GlobalDCE.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalDCE.cpp
@@ -416,6 +416,16 @@ PreservedAnalyses GlobalDCEPass::run(Module &M, ModuleAnalysisManager &MAM) {
// 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.
+ replaceRelativePointerUsersWithZero(F);
+
F->replaceNonMetadataUsesWith(ConstantPointerNull::get(F->getType()));
}
EraseUnusedGlobalValue(F);
diff --git a/llvm/test/Transforms/GlobalDCE/call-with-ptrtoint.ll b/llvm/test/Transforms/GlobalDCE/call-with-ptrtoint.ll
new file mode 100644
index 000000000000..bff769b34f7c
--- /dev/null
+++ b/llvm/test/Transforms/GlobalDCE/call-with-ptrtoint.ll
@@ -0,0 +1,21 @@
+; RUN: opt < %s -globaldce -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)
+
+define internal void @foo() {
+ call void @bar_with_fptr_argument(i64 ptrtoint (void ()* @baz to i64))
+ ret void
+}
+
+define internal void @bar_with_fptr_argument(i64 %0) {
+ ret void
+}
+
+define internal void @baz() {
+ ret void
+}
+
+!999 = !{i32 1, !"Virtual Function Elim", i32 1}
+!llvm.module.flags = !{!999}
diff --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-bad.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-bad.ll
index 9562d3db82e2..c386e6c71df6 100644
--- a/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-bad.ll
+++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-bad.ll
@@ -14,11 +14,7 @@ declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata)
!0 = !{i64 0, !"vfunc1.type"}
!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: ] }, align 8, !type !0, !type !1, !vcall_visibility !2
+; CHECK: @vtable = internal unnamed_addr constant { [3 x i32] } zeroinitializer, align 8, !type !0, !type !1, !vcall_visibility !2
define internal void @vfunc1() { ret void }
define internal void @vfunc2() { ret void }
diff --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-gep.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-gep.ll
index e49dc784af61..7ec29cc26f13 100644
--- a/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-gep.ll
+++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers-gep.ll
@@ -16,7 +16,7 @@ declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata)
; 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
diff --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers.ll
index c2bbf00ba56d..685f3754d2da 100644
--- a/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers.ll
+++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-relative-pointers.ll
@@ -14,7 +14,7 @@ declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata)
; 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
More information about the llvm-commits
mailing list