From 95d08bce87645180ff63ef7468f8042b559ca0f6 Mon Sep 17 00:00:00 2001 From: Swaroop Sridhar Date: Wed, 20 May 2015 01:07:23 +0000 Subject: [PATCH] Add a GCStrategy for CoreCLR This change adds a new GC strategy for supporting the CoreCLR runtime. This strategy is currently identical to Statepoint-example GC, but is necessary for several upcoming changes specific to CoreCLR, such as: 1. Base-pointers not explicitly reported for interior pointers 2. Different format for stack-map encoding 3. Location of Safe-point polls: polls are only needed before loop-back edges and before tail-calls (not needed at function-entry) 4. Runtime specific handshake between calls to managed/unmanaged functions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237753 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/GCs.h | 3 + .../llvm/CodeGen/LinkAllCodegenComponents.h | 1 + lib/CodeGen/CMakeLists.txt | 1 + lib/CodeGen/CoreCLRGC.cpp | 55 +++++++++++++++++++ lib/Transforms/Scalar/PlaceSafepoints.cpp | 8 ++- .../Scalar/RewriteStatepointsForGC.cpp | 11 +++- .../PlaceSafepoints/statepoint-coreclr.ll | 31 +++++++++++ 7 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 lib/CodeGen/CoreCLRGC.cpp create mode 100644 test/Transforms/PlaceSafepoints/statepoint-coreclr.ll diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index 5bae41ea030..64a01a3c1b4 100644 --- a/include/llvm/CodeGen/GCs.h +++ b/include/llvm/CodeGen/GCs.h @@ -21,6 +21,9 @@ class GCMetadataPrinter; /// FIXME: Collector instances are not useful on their own. These no longer /// serve any purpose except to link in the plugins. +/// Creates a CoreCLR-compatible garbage collector. +void linkCoreCLRGC(); + /// Creates an ocaml-compatible garbage collector. void linkOcamlGC(); diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index e7ccbfa617e..fee131e4a3c 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -36,6 +36,7 @@ namespace { (void) llvm::createGreedyRegisterAllocator(); (void) llvm::createDefaultPBQPRegisterAllocator(); + llvm::linkCoreCLRGC(); llvm::linkOcamlGC(); llvm::linkErlangGC(); llvm::linkShadowStackGC(); diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index 6ce5b13ea39..9fc3e0bcec9 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -9,6 +9,7 @@ add_llvm_library(LLVMCodeGen CallingConvLower.cpp CodeGen.cpp CodeGenPrepare.cpp + CoreCLRGC.cpp CriticalAntiDepBreaker.cpp DFAPacketizer.cpp DeadMachineInstructionElim.cpp diff --git a/lib/CodeGen/CoreCLRGC.cpp b/lib/CodeGen/CoreCLRGC.cpp new file mode 100644 index 00000000000..2726180be40 --- /dev/null +++ b/lib/CodeGen/CoreCLRGC.cpp @@ -0,0 +1,55 @@ +//===-- CoreCLRGC.cpp - CoreCLR Runtime GC Strategy -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a GCStrategy for the CoreCLR Runtime. +// The strategy is similar to Statepoint-example GC, but differs from it in +// certain aspects, such as: +// 1) Base-pointers need not be explicitly tracked and reported for +// interior pointers +// 2) Uses a different format for encoding stack-maps +// 3) Location of Safe-point polls: polls are only needed before loop-back edges +// and before tail-calls (not needed at function-entry) +// +// The above differences in behavior are to be implemented in upcoming checkins. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Value.h" + +using namespace llvm; + +namespace { +class CoreCLRGC : public GCStrategy { +public: + CoreCLRGC() { + UseStatepoints = true; + // These options are all gc.root specific, we specify them so that the + // gc.root lowering code doesn't run. + InitRoots = false; + NeededSafePoints = 0; + UsesMetadata = false; + CustomRoots = false; + } + Optional isGCManagedPointer(const Value *V) const override { + // Method is only valid on pointer typed values. + PointerType *PT = cast(V->getType()); + // We pick addrspace(1) as our GC managed heap. + return (1 == PT->getAddressSpace()); + } +}; +} + +static GCRegistry::Add X("coreclr", + "CoreCLR-compatible GC"); + +namespace llvm { +void linkCoreCLRGC() {} +} diff --git a/lib/Transforms/Scalar/PlaceSafepoints.cpp b/lib/Transforms/Scalar/PlaceSafepoints.cpp index fc1453b3175..9e7a4d8febc 100644 --- a/lib/Transforms/Scalar/PlaceSafepoints.cpp +++ b/lib/Transforms/Scalar/PlaceSafepoints.cpp @@ -53,6 +53,7 @@ #include "llvm/ADT/SetOperations.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/ScalarEvolution.h" @@ -523,8 +524,11 @@ static bool isGCSafepointPoll(Function &F) { static bool shouldRewriteFunction(Function &F) { // TODO: This should check the GCStrategy if (F.hasGC()) { - const std::string StatepointExampleName("statepoint-example"); - return StatepointExampleName == F.getGC(); + const char *FunctionGCName = F.getGC(); + const StringRef StatepointExampleName("statepoint-example"); + const StringRef CoreCLRName("coreclr"); + return (StatepointExampleName == FunctionGCName) || + (CoreCLRName == FunctionGCName); } else return false; } diff --git a/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp index a692d61bfa6..505070552c1 100644 --- a/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ b/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Dominators.h" @@ -2201,9 +2202,13 @@ static bool insertParsePoints(Function &F, DominatorTree &DT, Pass *P, static bool shouldRewriteStatepointsIn(Function &F) { // TODO: This should check the GCStrategy if (F.hasGC()) { - const std::string StatepointExampleName("statepoint-example"); - return StatepointExampleName == F.getGC(); - } else + const char *FunctionGCName = F.getGC(); + const StringRef StatepointExampleName("statepoint-example"); + const StringRef CoreCLRName("coreclr"); + return (StatepointExampleName == FunctionGCName) || + (CoreCLRName == FunctionGCName); + } + else return false; } diff --git a/test/Transforms/PlaceSafepoints/statepoint-coreclr.ll b/test/Transforms/PlaceSafepoints/statepoint-coreclr.ll new file mode 100644 index 00000000000..dc468966877 --- /dev/null +++ b/test/Transforms/PlaceSafepoints/statepoint-coreclr.ll @@ -0,0 +1,31 @@ +; RUN: opt %s -S -place-safepoints | FileCheck %s + +; Basic test to make sure that safepoints are placed +; for CoreCLR GC + +declare void @foo() + +define void @test_simple_call() gc "coreclr" { +; CHECK-LABEL: test_simple_call +entry: + br label %other +other: +; CHECK-LABEL: other +; CHECK: statepoint +; CHECK-NOT: gc.result + call void @foo() + ret void +} + +; This function is inlined when inserting a poll. To avoid recursive +; issues, make sure we don't place safepoints in it. +declare void @do_safepoint() +define void @gc.safepoint_poll() { +; CHECK-LABEL: gc.safepoint_poll +; CHECK-LABEL: entry +; CHECK-NEXT: do_safepoint +; CHECK-NEXT: ret void +entry: + call void @do_safepoint() + ret void +} -- 2.34.1