[llvm] cd220a0 - [NewPM] Add C bindings for new pass manager

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Mon May 17 10:49:07 PDT 2021


Author: Mats Larsen
Date: 2021-05-17T10:48:45-07:00
New Revision: cd220a06782c3da13a53de2fdf10d928eef6460c

URL: https://github.com/llvm/llvm-project/commit/cd220a06782c3da13a53de2fdf10d928eef6460c
DIFF: https://github.com/llvm/llvm-project/commit/cd220a06782c3da13a53de2fdf10d928eef6460c.diff

LOG: [NewPM] Add C bindings for new pass manager

This patch contains the bare minimum to run the new Pass Manager from the LLVM-C APIs. It does not feature PGOOptions, PassPlugins or Debugify in its current state. Bugzilla: PR48499

Reviewed By: aeubanks

Differential Revision: https://reviews.llvm.org/D102136

Added: 
    llvm/include/llvm-c/Transforms/PassBuilder.h
    llvm/lib/Passes/PassBuilderBindings.cpp
    llvm/unittests/Passes/PassBuilderBindingsTest.cpp

Modified: 
    llvm/lib/Passes/CMakeLists.txt
    llvm/unittests/Passes/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm-c/Transforms/PassBuilder.h b/llvm/include/llvm-c/Transforms/PassBuilder.h
new file mode 100644
index 000000000000..4e32900142f2
--- /dev/null
+++ b/llvm/include/llvm-c/Transforms/PassBuilder.h
@@ -0,0 +1,105 @@
+/*===-- llvm-c/Transform/PassBuilder.h - PassBuilder for LLVM C ---*- C -*-===*\
+|*                                                                            *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM          *|
+|* Exceptions.                                                                *|
+|* See https://llvm.org/LICENSE.txt for license information.                  *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception                    *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This header contains the LLVM-C interface into the new pass manager        *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_C_TRANSFORMS_PASSBUILDER_H
+#define LLVM_C_TRANSFORMS_PASSBUILDER_H
+
+#include "llvm-c/Error.h"
+#include "llvm-c/TargetMachine.h"
+#include "llvm-c/Types.h"
+
+LLVM_C_EXTERN_C_BEGIN
+
+/**
+ * A set of options passed which are attached to the Pass Manager upon run.
+ *
+ * This corresponds to an llvm::LLVMPassBuilderOptions instance
+ *
+ * The details for how the 
diff erent properties of this structure are used can
+ * be found in the source for LLVMRunPasses
+ */
+typedef struct LLVMOpaquePassBuilderOptions *LLVMPassBuilderOptionsRef;
+
+/**
+ * Construct and run a set of passes over a module
+ *
+ * This function takes a string with the passes that should be used. The format
+ * of this string is the same as opt's -passes argument for the new pass
+ * manager. Individual passes may be specified, separated by commas. Full
+ * pipelines may also be invoked using `default<O3>` and friends. See opt for
+ * full reference of the Passes format.
+ */
+LLVMErrorRef LLVMRunPasses(LLVMModuleRef M, const char *Passes,
+                           LLVMTargetMachineRef TM,
+                           LLVMPassBuilderOptionsRef Options);
+
+/**
+ * Create a new set of options for a PassBuilder
+ *
+ * Ownership of the returned instance is given to the client, and they are
+ * responsible for it. The client should call LLVMDisposePassBuilderOptions
+ * to free the pass builder options.
+ */
+LLVMPassBuilderOptionsRef LLVMCreatePassBuilderOptions();
+
+/**
+ * Toggle adding the VerifierPass for the PassBuilder, ensuring all functions
+ * inside the module is valid.
+ */
+void LLVMPassBuilderOptionsSetVerifyEach(LLVMPassBuilderOptionsRef Options,
+                                         LLVMBool VerifyEach);
+
+/**
+ * Toggle debug logging when running the PassBuilder
+ */
+void LLVMPassBuilderOptionsSetDebugLogging(LLVMPassBuilderOptionsRef Options,
+                                           LLVMBool DebugLogging);
+
+void LLVMPassBuilderOptionsSetLoopInterleaving(
+    LLVMPassBuilderOptionsRef Options, LLVMBool LoopInterleaving);
+
+void LLVMPassBuilderOptionsSetLoopVectorization(
+    LLVMPassBuilderOptionsRef Options, LLVMBool LoopVectorization);
+
+void LLVMPassBuilderOptionsSetSLPVectorization(
+    LLVMPassBuilderOptionsRef Options, LLVMBool SLPVectorization);
+
+void LLVMPassBuilderOptionsSetLoopUnrolling(LLVMPassBuilderOptionsRef Options,
+                                            LLVMBool LoopUnrolling);
+
+void LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(
+    LLVMPassBuilderOptionsRef Options, LLVMBool ForgetAllSCEVInLoopUnroll);
+
+void LLVMPassBuilderOptionsSetCoroutines(LLVMPassBuilderOptionsRef Options,
+                                         LLVMBool Coroutines);
+
+void LLVMPassBuilderOptionsSetLicmMssaOptCap(LLVMPassBuilderOptionsRef Options,
+                                             unsigned LicmMssaOptCap);
+
+void LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap(
+    LLVMPassBuilderOptionsRef Options, unsigned LicmMssaNoAccForPromotionCap);
+
+void LLVMPassBuilderOptionsSetCallGraphProfile(
+    LLVMPassBuilderOptionsRef Options, LLVMBool CallGraphProfile);
+
+void LLVMPassBuilderOptionsSetMergeFunctions(LLVMPassBuilderOptionsRef Options,
+                                             LLVMBool MergeFunctions);
+
+/**
+ * Dispose of a heap-allocated PassBuilderOptions instance
+ */
+void LLVMDisposePassBuilderOptions(LLVMPassBuilderOptionsRef Options);
+
+LLVM_C_EXTERN_C_END
+
+#endif // LLVM_C_TRANSFORMS_PASSBUILDER_H

diff  --git a/llvm/lib/Passes/CMakeLists.txt b/llvm/lib/Passes/CMakeLists.txt
index f517136223ec..89e960f01e2e 100644
--- a/llvm/lib/Passes/CMakeLists.txt
+++ b/llvm/lib/Passes/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_llvm_component_library(LLVMPasses
   PassBuilder.cpp
+  PassBuilderBindings.cpp
   PassPlugin.cpp
   StandardInstrumentations.cpp
 

diff  --git a/llvm/lib/Passes/PassBuilderBindings.cpp b/llvm/lib/Passes/PassBuilderBindings.cpp
new file mode 100644
index 000000000000..1a344a4a4954
--- /dev/null
+++ b/llvm/lib/Passes/PassBuilderBindings.cpp
@@ -0,0 +1,149 @@
+//===-------------- PassBuilder bindings for LLVM-C -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the C bindings to the new pass manager
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/Transforms/PassBuilder.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/StandardInstrumentations.h"
+#include "llvm/Support/CBindingWrapping.h"
+
+using namespace llvm;
+
+namespace llvm {
+/// Helper struct for holding a set of builder options for LLVMRunPasses. This
+/// structure is used to keep LLVMRunPasses backwards compatible with future
+/// versions in case we modify the options the new Pass Manager utilizes.
+class LLVMPassBuilderOptions {
+public:
+  explicit LLVMPassBuilderOptions(
+      bool DebugLogging = false, bool VerifyEach = false,
+      PipelineTuningOptions PTO = PipelineTuningOptions())
+      : DebugLogging(DebugLogging), VerifyEach(VerifyEach), PTO(PTO) {}
+
+  bool DebugLogging;
+  bool VerifyEach;
+  PipelineTuningOptions PTO;
+};
+} // namespace llvm
+
+static TargetMachine *unwrap(LLVMTargetMachineRef P) {
+  return reinterpret_cast<TargetMachine *>(P);
+}
+
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMPassBuilderOptions,
+                                   LLVMPassBuilderOptionsRef)
+
+LLVMErrorRef LLVMRunPasses(LLVMModuleRef M, const char *Passes,
+                           LLVMTargetMachineRef TM,
+                           LLVMPassBuilderOptionsRef Options) {
+  TargetMachine *Machine = unwrap(TM);
+  LLVMPassBuilderOptions *PassOpts = unwrap(Options);
+  bool Debug = PassOpts->DebugLogging;
+  bool VerifyEach = PassOpts->VerifyEach;
+
+  Module *Mod = unwrap(M);
+  PassInstrumentationCallbacks PIC;
+  PassBuilder PB(Debug, Machine, PassOpts->PTO, None, &PIC);
+
+  LoopAnalysisManager LAM(Debug);
+  FunctionAnalysisManager FAM(Debug);
+  CGSCCAnalysisManager CGAM(Debug);
+  ModuleAnalysisManager MAM(Debug);
+  PB.registerLoopAnalyses(LAM);
+  PB.registerFunctionAnalyses(FAM);
+  PB.registerCGSCCAnalyses(CGAM);
+  PB.registerModuleAnalyses(MAM);
+  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+  StandardInstrumentations SI(Debug, VerifyEach);
+  SI.registerCallbacks(PIC, &FAM);
+  ModulePassManager MPM(Debug);
+  if (VerifyEach) {
+    MPM.addPass(VerifierPass());
+  }
+  if (auto Err = PB.parsePassPipeline(MPM, Passes)) {
+    return wrap(std::move(Err));
+  }
+
+  MPM.run(*Mod, MAM);
+  return LLVMErrorSuccess;
+}
+
+LLVMPassBuilderOptionsRef LLVMCreatePassBuilderOptions() {
+  return wrap(new LLVMPassBuilderOptions());
+}
+
+void LLVMPassBuilderOptionsSetVerifyEach(LLVMPassBuilderOptionsRef Options,
+                                         LLVMBool VerifyEach) {
+  unwrap(Options)->VerifyEach = VerifyEach;
+}
+
+void LLVMPassBuilderOptionsSetDebugLogging(LLVMPassBuilderOptionsRef Options,
+                                           LLVMBool DebugLogging) {
+  unwrap(Options)->DebugLogging = DebugLogging;
+}
+
+void LLVMPassBuilderOptionsSetLoopInterleaving(
+    LLVMPassBuilderOptionsRef Options, LLVMBool LoopInterleaving) {
+  unwrap(Options)->PTO.LoopInterleaving = LoopInterleaving;
+}
+
+void LLVMPassBuilderOptionsSetLoopVectorization(
+    LLVMPassBuilderOptionsRef Options, LLVMBool LoopVectorization) {
+  unwrap(Options)->PTO.LoopVectorization = LoopVectorization;
+}
+
+void LLVMPassBuilderOptionsSetSLPVectorization(
+    LLVMPassBuilderOptionsRef Options, LLVMBool SLPVectorization) {
+  unwrap(Options)->PTO.SLPVectorization = SLPVectorization;
+}
+
+void LLVMPassBuilderOptionsSetLoopUnrolling(LLVMPassBuilderOptionsRef Options,
+                                            LLVMBool LoopUnrolling) {
+  unwrap(Options)->PTO.LoopUnrolling = LoopUnrolling;
+}
+
+void LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(
+    LLVMPassBuilderOptionsRef Options, LLVMBool ForgetAllSCEVInLoopUnroll) {
+  unwrap(Options)->PTO.ForgetAllSCEVInLoopUnroll = ForgetAllSCEVInLoopUnroll;
+}
+
+void LLVMPassBuilderOptionsSetCoroutines(LLVMPassBuilderOptionsRef Options,
+                                         LLVMBool Coroutines) {
+  unwrap(Options)->PTO.Coroutines = Coroutines;
+}
+
+void LLVMPassBuilderOptionsSetLicmMssaOptCap(LLVMPassBuilderOptionsRef Options,
+                                             unsigned LicmMssaOptCap) {
+  unwrap(Options)->PTO.LicmMssaOptCap = LicmMssaOptCap;
+}
+
+void LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap(
+    LLVMPassBuilderOptionsRef Options, unsigned LicmMssaNoAccForPromotionCap) {
+  unwrap(Options)->PTO.LicmMssaNoAccForPromotionCap =
+      LicmMssaNoAccForPromotionCap;
+}
+
+void LLVMPassBuilderOptionsSetCallGraphProfile(
+    LLVMPassBuilderOptionsRef Options, LLVMBool CallGraphProfile) {
+  unwrap(Options)->PTO.CallGraphProfile = CallGraphProfile;
+}
+
+void LLVMPassBuilderOptionsSetMergeFunctions(LLVMPassBuilderOptionsRef Options,
+                                             LLVMBool MergeFunctions) {
+  unwrap(Options)->PTO.MergeFunctions = MergeFunctions;
+}
+
+void LLVMDisposePassBuilderOptions(LLVMPassBuilderOptionsRef Options) {
+  delete unwrap(Options);
+}

diff  --git a/llvm/unittests/Passes/CMakeLists.txt b/llvm/unittests/Passes/CMakeLists.txt
index 823bc56851fa..c78003dde991 100644
--- a/llvm/unittests/Passes/CMakeLists.txt
+++ b/llvm/unittests/Passes/CMakeLists.txt
@@ -1,5 +1,5 @@
 # Needed by LLVM's CMake checks because this file defines multiple targets.
-set(LLVM_OPTIONAL_SOURCES PluginsTest.cpp TestPlugin.cpp)
+set(LLVM_OPTIONAL_SOURCES PluginsTest.cpp TestPlugin.cpp PassBuilderBindingsTest.cpp)
 
 # If plugins are disabled, this test will disable itself at runtime. Otherwise,
 # reconfiguring with plugins disabled will leave behind a stale executable.
@@ -34,3 +34,7 @@ if (NOT WIN32)
   add_dependencies(TestPlugin intrinsics_gen)
   add_dependencies(PluginsTests TestPlugin)
 endif()
+
+set(LLVM_LINK_COMPONENTS Support Passes Core Target native)
+add_llvm_unittest(PassesBindingsTests PassBuilderBindingsTest.cpp)
+target_link_libraries(PassesBindingsTests PRIVATE LLVMTestingSupport)
\ No newline at end of file

diff  --git a/llvm/unittests/Passes/PassBuilderBindingsTest.cpp b/llvm/unittests/Passes/PassBuilderBindingsTest.cpp
new file mode 100644
index 000000000000..93772c8db2cb
--- /dev/null
+++ b/llvm/unittests/Passes/PassBuilderBindingsTest.cpp
@@ -0,0 +1,67 @@
+//===- unittests/Passes/PassBuilderBindingsTest.cpp -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/Core.h"
+#include "llvm-c/Transforms/PassBuilder.h"
+#include "llvm-c/Types.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+class PassBuilderCTest : public testing::Test {
+  void SetUp() override {
+    LLVMInitializeNativeTarget();
+    const char *Triple = LLVMGetDefaultTargetTriple();
+    char *Err;
+    LLVMTargetRef Target;
+    if (LLVMGetTargetFromTriple(Triple, &Target, &Err)) {
+      FAIL() << "Failed to create target from default triple: " << Err;
+    }
+    TM = LLVMCreateTargetMachine(Target, Triple, "generic", "",
+                                 LLVMCodeGenLevelDefault, LLVMRelocDefault,
+                                 LLVMCodeModelDefault);
+    Context = LLVMContextCreate();
+    Module = LLVMModuleCreateWithNameInContext("test", Context);
+  }
+
+  void TearDown() override {
+    LLVMDisposeTargetMachine(TM);
+    LLVMDisposeModule(Module);
+    LLVMContextDispose(Context);
+  }
+
+public:
+  LLVMTargetMachineRef TM;
+  LLVMModuleRef Module;
+  LLVMContextRef Context;
+};
+
+TEST_F(PassBuilderCTest, Basic) {
+  LLVMPassBuilderOptionsRef Options = LLVMCreatePassBuilderOptions();
+  LLVMPassBuilderOptionsSetLoopUnrolling(Options, 1);
+  LLVMPassBuilderOptionsSetVerifyEach(Options, 1);
+  LLVMPassBuilderOptionsSetDebugLogging(Options, 0);
+  if (LLVMErrorRef E = LLVMRunPasses(TM, Module, Options, "default<O2>")) {
+    char *Msg = LLVMGetErrorMessage(E);
+    LLVMConsumeError(E);
+    LLVMDisposePassBuilderOptions(Options);
+    FAIL() << "Failed to run passes: " << Msg;
+  }
+  LLVMDisposePassBuilderOptions(Options);
+}
+
+TEST_F(PassBuilderCTest, InvalidPassIsError) {
+  LLVMPassBuilderOptionsRef Options = LLVMCreatePassBuilderOptions();
+  LLVMErrorRef E1 = LLVMRunPasses(TM, Module, Options, "");
+  LLVMErrorRef E2 = LLVMRunPasses(TM, Module, Options, "does-not-exist-pass");
+  ASSERT_TRUE(E1);
+  ASSERT_TRUE(E2);
+  LLVMConsumeError(E1);
+  LLVMConsumeError(E2);
+  LLVMDisposePassBuilderOptions(Options);
+}


        


More information about the llvm-commits mailing list