llvm.org GIT mirror llvm / 28fa9e1
Introduce an example statepoint GC strategy This change includes the most basic possible GCStrategy for a GC which is using the statepoint lowering code. At the moment, this GCStrategy doesn't really do much - aside from actually generate correct stackmaps that is - but I went ahead and added a few extra correctness checks as proof of concept. It's mostly here to provide documentation on how to do one, and to provide a point for various optimization legality hooks I'd like to add going forward. (For context, see the TODOs in InstCombine around gc.relocate.) Most of the validation logic added here as proof of concept will soon move in to the Verifier. That move is dependent on http://reviews.llvm.org/D6811 There was discussion in the review thread about addrspace(1) being reserved for something. I'm going to follow up on a seperate llvmdev thread. If needed, I'll update all the code at once. Note that I am deliberately not making a GCStrategy required to use gc.statepoints with this change. I want to give folks out of tree - including myself - a chance to migrate. In a week or two, I'll make having a GCStrategy be required for gc.statepoints. To this end, I added the gc tag to one of the test cases but not others. Differential Revision: http://reviews.llvm.org/D6808 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225365 91177308-0d34-0410-b5e6-96231b3b80d8 Philip Reames 5 years ago
8 changed file(s) with 81 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
4949 #ifndef LLVM_CODEGEN_GCSTRATEGY_H
5050 #define LLVM_CODEGEN_GCSTRATEGY_H
5151
52 #include "llvm/ADT/Optional.h"
5253 #include "llvm/CodeGen/GCMetadata.h"
5354 #include "llvm/CodeGen/MachineFunction.h"
5455 #include "llvm/Support/Registry.h"
6667 friend class GCModuleInfo;
6768
6869 protected:
70 bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots,
71 /// if set, none of the other options can be
72 /// anything but their default values.
73
6974 unsigned NeededSafePoints; ///< Bitmask of required safe points.
7075 bool CustomReadBarriers; ///< Default is to insert loads.
7176 bool CustomWriteBarriers; ///< Default is to insert stores.
9297 /// instructions. If true, then performCustomLowering must instead lower
9398 /// them.
9499 bool customReadBarrier() const { return CustomReadBarriers; }
100
101 /// Returns true if this strategy is expecting the use of gc.statepoints,
102 /// and false otherwise.
103 bool useStatepoints() const { return UseStatepoints; }
104
105 /** @name Statepoint Specific Properties */
106 ///@{
107
108 /// If the value specified can be reliably distinguished, returns true for
109 /// pointers to GC managed locations and false for pointers to non-GC
110 /// managed locations. Note a GCStrategy can always return 'None' (i.e. an
111 /// empty optional indicating it can't reliably distinguish.
112 virtual Optional isGCManagedPointer(const Value *V) const {
113 return None;
114 }
115 ///@}
95116
96117 /** @name GCRoot Specific Properties
97118 * These properties and overrides only apply to collector strategies using
125146 bool initializeRoots() const { return InitRoots; }
126147
127148 /// If set, appropriate metadata tables must be emitted by the back-end
128 /// (assembler, JIT, or otherwise).
149 /// (assembler, JIT, or otherwise). For statepoint, this method is
150 /// currently unsupported. The stackmap information can be found in the
151 /// StackMap section as described in the documentation.
129152 bool usesMetadata() const { return UsesMetadata; }
130153
131154 ///@}
3535 /// Creates a shadow stack garbage collector. This collector requires no code
3636 /// generator support.
3737 void linkShadowStackGC();
38
39 void linkStatepointExampleGC();
3840 }
3941
4042 #endif
3838 llvm::linkOcamlGC();
3939 llvm::linkErlangGC();
4040 llvm::linkShadowStackGC();
41 llvm::linkStatepointExampleGC();
4142
4243 (void) llvm::createBURRListDAGScheduler(nullptr,
4344 llvm::CodeGenOpt::Default);
22932293 if (!S.usesMetadata())
22942294 return nullptr;
22952295
2296 assert(!S.useStatepoints() && "statepoints do not currently support custom"
2297 " stackmap formats, please see the documentation for a description of"
2298 " the default format. If you really need a custom serialized format,"
2299 " please file a bug");
2300
22962301 gcp_map_type &GCMap = getGCMap(GCMetadataPrinters);
22972302 gcp_map_type::iterator GCPI = GCMap.find(&S);
22982303 if (GCPI != GCMap.end())
103103 StackSlotColoring.cpp
104104 StackMapLivenessAnalysis.cpp
105105 StackMaps.cpp
106 StatepointExampleGC.cpp
106107 TailDuplication.cpp
107108 TargetFrameLoweringImpl.cpp
108109 TargetInstrInfo.cpp
9292 // -----------------------------------------------------------------------------
9393
9494 GCStrategy::GCStrategy() :
95 UseStatepoints(false),
9596 NeededSafePoints(0),
9697 CustomReadBarriers(false),
9798 CustomWriteBarriers(false),
1616 #include "llvm/ADT/SmallSet.h"
1717 #include "llvm/ADT/Statistic.h"
1818 #include "llvm/CodeGen/FunctionLoweringInfo.h"
19 #include "llvm/CodeGen/GCStrategy.h"
1920 #include "llvm/CodeGen/SelectionDAG.h"
2021 #include "llvm/CodeGen/StackMaps.h"
2122 #include "llvm/IR/CallingConv.h"
416417 getIncomingStatepointGCValues(Bases, Ptrs, Relocations,
417418 Statepoint.getCallSite(), Builder);
418419
420 #ifndef NDEBUG
421 // Check that each of the gc pointer and bases we've gotten out of the
422 // safepoint is something the strategy thinks might be a pointer into the GC
423 // heap. This is basically just here to help catch errors during statepoint
424 // insertion. TODO: This should actually be in the Verifier, but we can't get
425 // to the GCStrategy from there (yet).
426 if (Builder.GFI) {
427 GCStrategy &S = Builder.GFI->getStrategy();
428 for (const Value *V : Bases) {
429 auto Opt = S.isGCManagedPointer(V);
430 if (Opt.hasValue()) {
431 assert(Opt.getValue() &&
432 "non gc managed base pointer found in statepoint");
433 }
434 }
435 for (const Value *V : Ptrs) {
436 auto Opt = S.isGCManagedPointer(V);
437 if (Opt.hasValue()) {
438 assert(Opt.getValue() &&
439 "non gc managed derived pointer found in statepoint");
440 }
441 }
442 for (const Value *V : Relocations) {
443 auto Opt = S.isGCManagedPointer(V);
444 if (Opt.hasValue()) {
445 assert(Opt.getValue() && "non gc managed pointer relocated");
446 }
447 }
448 }
449 #endif
450
451
452
419453 // Before we actually start lowering (and allocating spill slots for values),
420454 // reserve any stack slots which we judge to be profitable to reuse for a
421455 // particular value. This is purely an optimization over the code below and
497531 // This should catch any IR level mistake that's made when constructing or
498532 // transforming statepoints.
499533 ISP.verify();
534
535 // Check that the associated GCStrategy expects to encounter statepoints.
536 // TODO: This if should become an assert. For now, we allow the GCStrategy
537 // to be optional for backwards compatibility. This will only last a short
538 // period (i.e. a couple of weeks).
539 if (GFI) {
540 assert(GFI->getStrategy().useStatepoints() &&
541 "GCStrategy does not expect to encounter statepoints");
542 }
500543 #endif
501544
502545
1919 ;; Forwarding the value of a pointer load is invalid since it may have
2020 ;; changed at the safepoint. Forwarding a non-gc pointer value would
2121 ;; be valid, but is not currently implemented.
22 define i1 @test_load_forward(i32 addrspace(1)* addrspace(1)* %p) {
22 define i1 @test_load_forward(i32 addrspace(1)* addrspace(1)* %p) gc "statepoint-example" {
2323 entry:
2424 %before = load i32 addrspace(1)* addrspace(1)* %p
2525 %cmp1 = call i1 @f(i32 addrspace(1)* %before)
3838
3939 ;; Same as above, but forwarding from a store
4040 define i1 @test_store_forward(i32 addrspace(1)* addrspace(1)* %p,
41 i32 addrspace(1)* %v) {
41 i32 addrspace(1)* %v) gc "statepoint-example" {
4242 entry:
4343 %cmp1 = call i1 @f(i32 addrspace(1)* %v)
4444 call void @llvm.assume(i1 %cmp1)
6666 ; that is not itself GC managed. The GC may have an external mechanism
6767 ; to know about and update that value at a safepoint. Note that the
6868 ; statepoint does not provide the collector with this root.
69 define i1 @test_load_forward_nongc_heap(i32 addrspace(1)** %p) {
69 define i1 @test_load_forward_nongc_heap(i32 addrspace(1)** %p) gc "statepoint-example" {
7070 entry:
7171 %before = load i32 addrspace(1)** %p
7272 %cmp1 = call i1 @f(i32 addrspace(1)* %before)
8484
8585 ;; Same as above, but forwarding from a store
8686 define i1 @test_store_forward_nongc_heap(i32 addrspace(1)** %p,
87 i32 addrspace(1)* %v) {
87 i32 addrspace(1)* %v) gc "statepoint-example" {
8888 entry:
8989 %cmp1 = call i1 @f(i32 addrspace(1)* %v)
9090 call void @llvm.assume(i1 %cmp1)
100100 ; CHECK-LLC: callq f
101101 }
102102
103
104103 declare void @llvm.assume(i1)
105104 declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()*, i32, i32, ...)
106105 declare i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32, i32, i32) #3