[PATCH] D75617: [WPD] Provide a way to prevent function(s) from being devirtualized

Eugene Leviant via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 4 09:00:28 PST 2020


evgeny777 created this revision.
evgeny777 added a reviewer: tejohnson.
Herald added a subscriber: hiraditya.
Herald added a project: LLVM.

https://reviews.llvm.org/D75617

Files:
  llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
  llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-check.ll


Index: llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-check.ll
===================================================================
--- llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-check.ll
+++ llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-check.ll
@@ -1,4 +1,12 @@
 ; RUN: opt -S -wholeprogramdevirt -whole-program-visibility -pass-remarks=wholeprogramdevirt %s 2>&1 | FileCheck %s
+; Skipping vf0i1 is identical to setting public LTO visibility. We don't devirtualize vf0i1 and all other
+; virtual call targets.
+; RUN: opt -S -wholeprogramdevirt -whole-program-visibility -pass-remarks=wholeprogramdevirt -wholeprogramdevirt-skip=vf0i1 %s 2>&1 | FileCheck %s --check-prefix=SKIP
+; We have two set of call targets {vf0i1, vf1i1} and {vf1i32, vf2i32, vf3i32, vf4i32}.
+; The command below prevents both of them from devirtualization.
+; RUN: opt -S -wholeprogramdevirt -whole-program-visibility -pass-remarks=wholeprogramdevirt -wholeprogramdevirt-skip=vf0i1,vf1i32 %s 2>&1 | FileCheck %s --check-prefix=SKIP-ALL
+; Check wildcard
+; RUN: opt -S -wholeprogramdevirt -whole-program-visibility -pass-remarks=wholeprogramdevirt -wholeprogramdevirt-skip=vf?i1 %s 2>&1 | FileCheck %s --check-prefix=SKIP
 
 target datalayout = "e-p:64:64"
 target triple = "x86_64-unknown-linux-gnu"
@@ -14,6 +22,14 @@
 ; CHECK: remark: <unknown>:0:0: devirtualized vf4i32
 ; CHECK-NOT: devirtualized
 
+; SKIP: remark: <unknown>:0:0: devirtualized vf1i32
+; SKIP: remark: <unknown>:0:0: devirtualized vf2i32
+; SKIP: remark: <unknown>:0:0: devirtualized vf3i32
+; SKIP: remark: <unknown>:0:0: devirtualized vf4i32
+; SKIP-NOT: devirtualized
+
+; SKIP-ALL-NOT: devirtualized
+
 ; CHECK: [[VT1DATA:@[^ ]*]] = private constant { [8 x i8], [3 x i8*], [0 x i8] } { [8 x i8] c"\00\00\00\01\01\00\00\00", [3 x i8*] [i8* bitcast (i1 (i8*)* @vf0i1 to i8*), i8* bitcast (i1 (i8*)* @vf1i1 to i8*), i8* bitcast (i32 (i8*)* @vf1i32 to i8*)], [0 x i8] zeroinitializer }, section "vt1sec", !type [[T8:![0-9]+]]
 @vt1 = constant [3 x i8*] [
 i8* bitcast (i1 (i8*)* @vf0i1 to i8*),
Index: llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
===================================================================
--- llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
+++ llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
@@ -91,6 +91,7 @@
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/GlobPattern.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/IPO/FunctionAttrs.h"
@@ -156,6 +157,12 @@
     cl::ZeroOrMore,
     cl::desc("Disable whole program visibility (overrides enabling options)"));
 
+/// Provide way to prevent certain function from being devirtualized
+cl::list<std::string>
+    SkipFunctionNames("wholeprogramdevirt-skip",
+                      cl::desc("Prevent function(s) from being devirtualized"),
+                      cl::ZeroOrMore, cl::CommaSeparated);
+
 // Find the minimum offset that we may store a value of size Size bits at. If
 // IsAfter is set, look for an offset before the object, otherwise look for an
 // offset after the object.
@@ -491,6 +498,7 @@
   // eliminate the type check by RAUWing the associated llvm.type.test call with
   // true.
   std::map<CallInst *, unsigned> NumUnsafeUsesForTypeTest;
+  std::vector<GlobPattern> FunctionsToSkip;
 
   DevirtModule(Module &M, function_ref<AAResults &(Function &)> AARGetter,
                function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter,
@@ -506,6 +514,9 @@
         IntPtrTy(M.getDataLayout().getIntPtrType(M.getContext(), 0)),
         RemarksEnabled(areRemarksEnabled()), OREGetter(OREGetter) {
     assert(!(ExportSummary && ImportSummary));
+    for (const std::string &Name : SkipFunctionNames)
+      if (Expected<GlobPattern> Pattern = GlobPattern::create(Name))
+        FunctionsToSkip.push_back(std::move(*Pattern));
   }
 
   bool areRemarksEnabled();
@@ -926,6 +937,10 @@
     if (!Fn)
       return false;
 
+    for (auto &SkipPattern : FunctionsToSkip)
+      if (SkipPattern.match(Fn->getName()))
+        return false;
+
     // We can disregard __cxa_pure_virtual as a possible call target, as
     // calls to pure virtuals are UB.
     if (Fn->getName() == "__cxa_pure_virtual")


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D75617.248189.patch
Type: text/x-patch
Size: 4328 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200304/829cbd6b/attachment-0001.bin>


More information about the llvm-commits mailing list