llvm.org GIT mirror llvm / 641414a
IR: Store RAUW support and Context in the same pointer, NFC Add an `LLVMContext &` to `ReplaceableMetadataImpl`, create a class that either holds a reference to an `LLVMContext` or owns a `ReplaceableMetadataImpl`, and use the new class in `MDNode`. - This saves a pointer in `UniquableMDNode` at the cost of a pointer in `ValueAsMetadata` (which didn't used to store the `LLVMContext`). There are far more of the former. - Unifies RAUW support between `MDNodeFwdDecl` (which is going away, see r226481) and `UniquableMDNode`. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226484 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 5 years ago
4 changed file(s) with 135 addition(s) and 24 deletion(s). Raw diff Collapse all Expand all
147147 typedef MetadataTracking::OwnerTy OwnerTy;
148148
149149 private:
150 LLVMContext &Context;
150151 uint64_t NextIndex;
151152 SmallDenseMap, 4> UseMap;
152153
153154 public:
154 ReplaceableMetadataImpl() : NextIndex(0) {}
155 ReplaceableMetadataImpl(LLVMContext &Context)
156 : Context(Context), NextIndex(0) {}
155157 ~ReplaceableMetadataImpl() {
156158 assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata");
157159 }
160
161 LLVMContext &getContext() const { return Context; }
158162
159163 /// \brief Replace all uses of this with MD.
160164 ///
197201
198202 protected:
199203 ValueAsMetadata(unsigned ID, Value *V)
200 : Metadata(ID, Uniqued), V(V) {
204 : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) {
201205 assert(V && "Expected valid value");
202206 }
203207 ~ValueAsMetadata() {}
582586 static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); }
583587 };
584588
589 /// \brief Pointer to the context, with optional RAUW support.
590 ///
591 /// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer
592 /// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext).
593 class ContextAndReplaceableUses {
594 PointerUnion Ptr;
595
596 ContextAndReplaceableUses() LLVM_DELETED_FUNCTION;
597 ContextAndReplaceableUses(ContextAndReplaceableUses &&)
598 LLVM_DELETED_FUNCTION;
599 ContextAndReplaceableUses(const ContextAndReplaceableUses &)
600 LLVM_DELETED_FUNCTION;
601 ContextAndReplaceableUses &
602 operator=(ContextAndReplaceableUses &&) LLVM_DELETED_FUNCTION;
603 ContextAndReplaceableUses &
604 operator=(const ContextAndReplaceableUses &) LLVM_DELETED_FUNCTION;
605
606 public:
607 ContextAndReplaceableUses(LLVMContext &Context) : Ptr(&Context) {}
608 ContextAndReplaceableUses(
609 std::unique_ptr ReplaceableUses)
610 : Ptr(ReplaceableUses.release()) {
611 assert(getReplaceableUses() && "Expected non-null replaceable uses");
612 }
613 ~ContextAndReplaceableUses() { delete getReplaceableUses(); }
614
615 operator LLVMContext &() { return getContext(); }
616
617 /// \brief Whether this contains RAUW support.
618 bool hasReplaceableUses() const {
619 return Ptr.is();
620 }
621 LLVMContext &getContext() const {
622 if (hasReplaceableUses())
623 return getReplaceableUses()->getContext();
624 return *Ptr.get();
625 }
626 ReplaceableMetadataImpl *getReplaceableUses() const {
627 if (hasReplaceableUses())
628 return Ptr.get();
629 return nullptr;
630 }
631
632 /// \brief Assign RAUW support to this.
633 ///
634 /// Make this replaceable, taking ownership of \c ReplaceableUses (which must
635 /// not be null).
636 void
637 makeReplaceable(std::unique_ptr ReplaceableUses) {
638 assert(ReplaceableUses && "Expected non-null replaceable uses");
639 assert(&ReplaceableUses->getContext() == &getContext() &&
640 "Expected same context");
641 delete getReplaceableUses();
642 Ptr = ReplaceableUses.release();
643 }
644
645 /// \brief Drop RAUW support.
646 ///
647 /// Cede ownership of RAUW support, returning it.
648 std::unique_ptr takeReplaceableUses() {
649 assert(hasReplaceableUses() && "Expected to own replaceable uses");
650 std::unique_ptr ReplaceableUses(
651 getReplaceableUses());
652 Ptr = &ReplaceableUses->getContext();
653 return ReplaceableUses;
654 }
655 };
656
585657 //===----------------------------------------------------------------------===//
586658 /// \brief Tuple of metadata.
587659 class MDNode : public Metadata {
660 friend class ReplaceableMetadataImpl;
661
588662 MDNode(const MDNode &) LLVM_DELETED_FUNCTION;
589663 void operator=(const MDNode &) LLVM_DELETED_FUNCTION;
590664 void *operator new(size_t) LLVM_DELETED_FUNCTION;
591665
592 LLVMContext &Context;
666 protected:
667 ContextAndReplaceableUses Context;
668
669 private:
593670 unsigned NumOperands;
594671
595672 protected:
637714 /// The node must not have any users.
638715 static void deleteTemporary(MDNode *N);
639716
640 LLVMContext &getContext() const { return Context; }
717 LLVMContext &getContext() const { return Context.getContext(); }
641718
642719 /// \brief Replace a specific operand.
643720 void replaceOperandWith(unsigned I, Metadata *New);
715792 friend class MDNode;
716793 friend class LLVMContextImpl;
717794
718 /// \brief Support RAUW as long as one of its arguments is replaceable.
719 ///
720 /// FIXME: Save memory by storing this in a pointer union with the
721 /// LLVMContext, and adding an LLVMContext reference to RMI.
722 std::unique_ptr ReplaceableUses;
723
724795 protected:
725796 /// \brief Create a new node.
726797 ///
747818 /// As forward declarations are resolved, their containers should get
748819 /// resolved automatically. However, if this (or one of its operands) is
749820 /// involved in a cycle, \a resolveCycles() needs to be called explicitly.
750 bool isResolved() const { return !ReplaceableUses; }
821 bool isResolved() const { return !Context.hasReplaceableUses(); }
751822
752823 /// \brief Resolve cycles.
753824 ///
883954 /// Forward declaration of metadata, in the form of a basic tuple. Unlike \a
884955 /// MDTuple, this class has full support for RAUW, is not owned, is not
885956 /// uniqued, and is suitable for forward references.
886 class MDNodeFwdDecl : public MDNode, ReplaceableMetadataImpl {
957 class MDNodeFwdDecl : public MDNode {
887958 friend class Metadata;
888 friend class ReplaceableMetadataImpl;
889959
890960 MDNodeFwdDecl(LLVMContext &C, ArrayRef Vals)
891961 : MDNode(C, MDNodeFwdDeclKind, Temporary, Vals) {}
904974 return MD->getMetadataID() == MDNodeFwdDeclKind;
905975 }
906976
907 using ReplaceableMetadataImpl::replaceAllUsesWith;
977 void replaceAllUsesWith(Metadata *MD) {
978 assert(Context.hasReplaceableUses() && "Expected RAUW support");
979 Context.getReplaceableUses()->replaceAllUsesWith(MD);
980 }
908981 };
909982
910983 //===----------------------------------------------------------------------===//
400400 MDNodeSubclassData(0) {
401401 for (unsigned I = 0, E = MDs.size(); I != E; ++I)
402402 setOperand(I, MDs[I]);
403
404 if (Storage == Temporary)
405 this->Context.makeReplaceable(
406 make_unique(Context));
403407 }
404408
405409 bool MDNode::isResolved() const {
428432 if (!NumUnresolved)
429433 return;
430434
431 ReplaceableUses.reset(new ReplaceableMetadataImpl);
435 this->Context.makeReplaceable(make_unique(C));
432436 SubclassData32 = NumUnresolved;
433437 }
434438
436440 assert(!isResolved() && "Expected this to be unresolved");
437441
438442 // Move the map, so that this immediately looks resolved.
439 auto Uses = std::move(ReplaceableUses);
443 auto Uses = Context.takeReplaceableUses();
440444 SubclassData32 = 0;
441445 assert(isResolved() && "Expected this to be resolved");
442446
498502 setOperand(I, nullptr);
499503 if (auto *N = dyn_cast(this))
500504 if (!N->isResolved()) {
501 N->ReplaceableUses->resolveAllUses(/* ResolveUsers */ false);
502 N->ReplaceableUses.reset();
505 N->Context.getReplaceableUses()->resolveAllUses(/* ResolveUsers */ false);
506 (void)N->Context.takeReplaceableUses();
503507 }
504508 }
505509
562566 // dropAllReferences(), but we still need the use-list).
563567 for (unsigned O = 0, E = getNumOperands(); O != E; ++O)
564568 setOperand(O, nullptr);
565 ReplaceableUses->replaceAllUsesWith(Uniqued);
569 Context.getReplaceableUses()->replaceAllUsesWith(Uniqued);
566570 deleteAsSubclass();
567571 return;
568572 }
1616 using namespace llvm;
1717
1818 ReplaceableMetadataImpl *ReplaceableMetadataImpl::get(Metadata &MD) {
19 if (auto *N = dyn_cast(&MD)) {
20 if (auto *U = dyn_cast(N))
21 return U->ReplaceableUses.get();
22 return cast(N);
23 }
19 if (auto *N = dyn_cast(&MD))
20 return N->Context.getReplaceableUses();
2421 return dyn_cast(&MD);
2522 }
2623
1818 using namespace llvm;
1919
2020 namespace {
21
22 TEST(ContextAndReplaceableUsesTest, FromContext) {
23 LLVMContext Context;
24 ContextAndReplaceableUses CRU(Context);
25 EXPECT_EQ(&Context, &CRU.getContext());
26 EXPECT_FALSE(CRU.hasReplaceableUses());
27 EXPECT_FALSE(CRU.getReplaceableUses());
28 }
29
30 TEST(ContextAndReplaceableUsesTest, FromReplaceableUses) {
31 LLVMContext Context;
32 ContextAndReplaceableUses CRU(make_unique(Context));
33 EXPECT_EQ(&Context, &CRU.getContext());
34 EXPECT_TRUE(CRU.hasReplaceableUses());
35 EXPECT_TRUE(CRU.getReplaceableUses());
36 }
37
38 TEST(ContextAndReplaceableUsesTest, makeReplaceable) {
39 LLVMContext Context;
40 ContextAndReplaceableUses CRU(Context);
41 CRU.makeReplaceable(make_unique(Context));
42 EXPECT_EQ(&Context, &CRU.getContext());
43 EXPECT_TRUE(CRU.hasReplaceableUses());
44 EXPECT_TRUE(CRU.getReplaceableUses());
45 }
46
47 TEST(ContextAndReplaceableUsesTest, takeReplaceableUses) {
48 LLVMContext Context;
49 auto ReplaceableUses = make_unique(Context);
50 auto *Ptr = ReplaceableUses.get();
51 ContextAndReplaceableUses CRU(std::move(ReplaceableUses));
52 ReplaceableUses = CRU.takeReplaceableUses();
53 EXPECT_EQ(&Context, &CRU.getContext());
54 EXPECT_FALSE(CRU.hasReplaceableUses());
55 EXPECT_FALSE(CRU.getReplaceableUses());
56 EXPECT_EQ(Ptr, ReplaceableUses.get());
57 }
2158
2259 class MetadataTest : public testing::Test {
2360 protected: