llvm.org GIT mirror llvm / 37c7ccc
IR: Allow temporary nodes to become uniqued or distinct Add `MDNode::replaceWithUniqued()` and `MDNode::replaceWithDistinct()`, which mutate temporary nodes to become uniqued or distinct. On uniquing collisions, the unique version is returned and the node is deleted. This takes advantage of temporary nodes being folded back in, and should let me clean up some awkward logic in `MapMetadata()`. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226510 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 5 years ago
3 changed file(s) with 161 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
743743 Context.getReplaceableUses()->replaceAllUsesWith(MD);
744744 }
745745
746 /// \brief Replace a temporary node with a uniqued one.
747 ///
748 /// Create a uniqued version of \c N -- in place, if possible -- and return
749 /// it. Takes ownership of the temporary node.
750 template
751 static typename std::enable_if::value,
752 T *>::type
753 replaceWithUniqued(std::unique_ptr N);
754
755 /// \brief Replace a temporary node with a distinct one.
756 ///
757 /// Create a distinct version of \c N -- in place, if possible -- and return
758 /// it. Takes ownership of the temporary node.
759 template
760 static typename std::enable_if::value,
761 T *>::type
762 replaceWithDistinct(std::unique_ptr N);
763
746764 protected:
747765 /// \brief Set an operand.
748766 ///
787805 static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
788806 };
789807
808 template
809 typename std::enable_if::value,
810 NodeTy *>::type
811 MDNode::replaceWithUniqued(std::unique_ptr Node) {
812 // Try to uniquify in place.
813 UniquableMDNode *UniquedNode = Node->uniquify();
814 if (UniquedNode == Node.get()) {
815 Node->makeUniqued();
816 return Node.release();
817 }
818
819 // Collision, so RAUW instead.
820 Node->replaceAllUsesWith(UniquedNode);
821 return cast(UniquedNode);
822 }
823
824 template
825 typename std::enable_if::value,
826 NodeTy *>::type
827 MDNode::replaceWithDistinct(std::unique_ptr Node) {
828 Node->makeDistinct();
829 return Node.release();
830 }
831
790832 /// \brief Uniquable metadata node.
791833 ///
792834 /// A uniquable metadata node. This contains the basic functionality
842884 void resolveAfterOperandChange(Metadata *Old, Metadata *New);
843885 void decrementUnresolvedOperandCount();
844886 unsigned countUnresolvedOperands() const;
887
888 /// \brief Mutate this to be "uniqued".
889 ///
890 /// Mutate this so that \a isUniqued().
891 /// \pre \a isTemporary().
892 /// \pre already added to uniquing set.
893 void makeUniqued();
894
895 /// \brief Mutate this to be "distinct".
896 ///
897 /// Mutate this so that \a isDistinct().
898 /// \pre \a isTemporary().
899 void makeDistinct();
845900
846901 void deleteAsSubclass();
847902 UniquableMDNode *uniquify();
435435 return NumUnresolved;
436436 }
437437
438 void UniquableMDNode::makeUniqued() {
439 assert(isTemporary() && "Expected this to be temporary");
440 assert(!isResolved() && "Expected this to be unresolved");
441
442 // Make this 'uniqued'.
443 Storage = Uniqued;
444 if (unsigned NumUnresolved = countUnresolvedOperands())
445 SubclassData32 = NumUnresolved;
446 else
447 resolve();
448
449 assert(isUniqued() && "Expected this to be uniqued");
450 }
451
452 void UniquableMDNode::makeDistinct() {
453 assert(isTemporary() && "Expected this to be temporary");
454 assert(!isResolved() && "Expected this to be unresolved");
455
456 // Pretend to be uniqued, resolve the node, and then store in distinct table.
457 Storage = Uniqued;
458 resolve();
459 storeDistinctInContext();
460
461 assert(isDistinct() && "Expected this to be distinct");
462 assert(isResolved() && "Expected this to be resolved");
463 }
464
438465 void UniquableMDNode::resolve() {
439466 assert(isUniqued() && "Expected this to be uniqued");
440467 assert(!isResolved() && "Expected this to be unresolved");
437437 Temp->replaceAllUsesWith(nullptr);
438438 }
439439
440 TEST_F(MDNodeTest, replaceWithUniqued) {
441 auto *Empty = MDTuple::get(Context, None);
442 MDTuple *FirstUniqued;
443 {
444 Metadata *Ops[] = {Empty};
445 auto Temp = MDTuple::getTemporary(Context, Ops);
446 EXPECT_TRUE(Temp->isTemporary());
447
448 // Don't expect a collision.
449 auto *Current = Temp.get();
450 FirstUniqued = MDNode::replaceWithUniqued(std::move(Temp));
451 EXPECT_TRUE(FirstUniqued->isUniqued());
452 EXPECT_TRUE(FirstUniqued->isResolved());
453 EXPECT_EQ(Current, FirstUniqued);
454 }
455 {
456 Metadata *Ops[] = {Empty};
457 auto Temp = MDTuple::getTemporary(Context, Ops);
458 EXPECT_TRUE(Temp->isTemporary());
459
460 // Should collide with Uniqued above this time.
461 auto *Uniqued = MDNode::replaceWithUniqued(std::move(Temp));
462 EXPECT_TRUE(Uniqued->isUniqued());
463 EXPECT_TRUE(Uniqued->isResolved());
464 EXPECT_EQ(FirstUniqued, Uniqued);
465 }
466 {
467 auto Unresolved = MDTuple::getTemporary(Context, None);
468 Metadata *Ops[] = {Unresolved.get()};
469 auto Temp = MDTuple::getTemporary(Context, Ops);
470 EXPECT_TRUE(Temp->isTemporary());
471
472 // Shouldn't be resolved.
473 auto *Uniqued = MDNode::replaceWithUniqued(std::move(Temp));
474 EXPECT_TRUE(Uniqued->isUniqued());
475 EXPECT_FALSE(Uniqued->isResolved());
476
477 // Should be a different node.
478 EXPECT_NE(FirstUniqued, Uniqued);
479
480 // Should resolve when we update its node (note: be careful to avoid a
481 // collision with any other nodes above).
482 Uniqued->replaceOperandWith(0, nullptr);
483 EXPECT_TRUE(Uniqued->isResolved());
484 }
485 }
486
487 TEST_F(MDNodeTest, replaceWithDistinct) {
488 {
489 auto *Empty = MDTuple::get(Context, None);
490 Metadata *Ops[] = {Empty};
491 auto Temp = MDTuple::getTemporary(Context, Ops);
492 EXPECT_TRUE(Temp->isTemporary());
493
494 // Don't expect a collision.
495 auto *Current = Temp.get();
496 auto *Distinct = MDNode::replaceWithDistinct(std::move(Temp));
497 EXPECT_TRUE(Distinct->isDistinct());
498 EXPECT_TRUE(Distinct->isResolved());
499 EXPECT_EQ(Current, Distinct);
500 }
501 {
502 auto Unresolved = MDTuple::getTemporary(Context, None);
503 Metadata *Ops[] = {Unresolved.get()};
504 auto Temp = MDTuple::getTemporary(Context, Ops);
505 EXPECT_TRUE(Temp->isTemporary());
506
507 // Don't expect a collision.
508 auto *Current = Temp.get();
509 auto *Distinct = MDNode::replaceWithDistinct(std::move(Temp));
510 EXPECT_TRUE(Distinct->isDistinct());
511 EXPECT_TRUE(Distinct->isResolved());
512 EXPECT_EQ(Current, Distinct);
513
514 // Cleanup; required for teardown.
515 Unresolved->replaceAllUsesWith(nullptr);
516 }
517 }
518
440519 typedef MetadataTest MDLocationTest;
441520
442521 TEST_F(MDLocationTest, Overflow) {