[PATCH] D112870: [MergeFunctions] Don't merge functions that use @llvm.type.checked.load instrinsics

Kuba (Brecka) Mracek via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 30 08:14:34 PDT 2021


kubamracek created this revision.
kubamracek added reviewers: pcc, fhahn, MaskRay, davide.
Herald added subscribers: ormris, hiraditya.
kubamracek requested review of this revision.
Herald added a project: LLVM.

See attached testcase that shows the miscompile / mis-merge. Comparing functions for equality is done via FunctionComparator, which only compares whether the two functions will produce the same machine code:

  /// FunctionComparator - Compares two functions to determine whether or not
  /// they will generate machine code with the same behaviour. 

Namely, this means that metadata attachments and metadata arguments of instructions are ignored, and that's a problem for @llvm.type.checked.load which does actually have an important meaningful metadata reference (type id).

This PR opts out functions that use @llvm.type.checked.load from merging.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D112870

Files:
  llvm/lib/Transforms/IPO/MergeFunctions.cpp
  llvm/test/Transforms/MergeFunc/merge-type-metadata.ll


Index: llvm/test/Transforms/MergeFunc/merge-type-metadata.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/MergeFunc/merge-type-metadata.ll
@@ -0,0 +1,23 @@
+; RUN: opt -S -mergefunc < %s | FileCheck %s
+
+; CHECK: @call_vfunc1
+define internal i32 @call_vfunc1(i8* %vtable) unnamed_addr {
+  %a = tail call { i8*, i1 } @llvm.type.checked.load(i8* %vtable, i32 0, metadata !"vtype1")
+  ret i32 0
+}
+
+; CHECK: @call_vfunc2
+define internal i32 @call_vfunc2(i8* %vtable) unnamed_addr {
+  %a = tail call { i8*, i1 } @llvm.type.checked.load(i8* %vtable, i32 0, metadata !"vtype2")
+  ret i32 0
+}
+
+declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata)
+
+define void @main() {
+  %a = call i32 @call_vfunc1(i8* null)
+  ; CHECK: call i32 @call_vfunc1
+  %b = call i32 @call_vfunc2(i8* null)
+  ; CHECK: call i32 @call_vfunc2
+  ret void
+}
Index: llvm/lib/Transforms/IPO/MergeFunctions.cpp
===================================================================
--- llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -403,19 +403,42 @@
 #endif
 
 /// Check whether \p F is eligible for function merging.
-static bool isEligibleForMerging(Function &F) {
-  return !F.isDeclaration() && !F.hasAvailableExternallyLinkage();
+static bool
+isEligibleForMerging(Function &F,
+                     std::set<Function *> TypeCheckedLoadUsingFuncs) {
+  if (F.isDeclaration() || F.hasAvailableExternallyLinkage())
+    return false;
+
+  if (TypeCheckedLoadUsingFuncs.count(&F))
+    return false;
+
+  return true;
 }
 
 bool MergeFunctions::runOnModule(Module &M) {
   bool Changed = false;
 
+  // Functions that use @llvm.type.checked.load intrinsic calls are not eligible
+  // for merging because the type metadata is not considered meaningful when
+  // comparing functions for equality. Let's find such functions.
+  Function *TypeCheckedLoadFunc =
+      M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load));
+  std::set<Function *> TypeCheckedLoadUsingFuncs;
+  if (TypeCheckedLoadFunc) {
+    for (auto U : TypeCheckedLoadFunc->users()) {
+      auto CI = dyn_cast<CallInst>(U);
+      if (!CI)
+        continue;
+      TypeCheckedLoadUsingFuncs.insert(CI->getFunction());
+    }
+  }
+
   // All functions in the module, ordered by hash. Functions with a unique
   // hash value are easily eliminated.
   std::vector<std::pair<FunctionComparator::FunctionHash, Function *>>
     HashedFuncs;
   for (Function &Func : M) {
-    if (isEligibleForMerging(Func)) {
+    if (isEligibleForMerging(Func, TypeCheckedLoadUsingFuncs)) {
       HashedFuncs.push_back({FunctionComparator::functionHash(Func), &Func});
     }
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D112870.383589.patch
Type: text/x-patch
Size: 2743 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20211030/0a97600c/attachment.bin>


More information about the llvm-commits mailing list