llvm.org GIT mirror llvm / e3394d4
When a constant's type is refined, update the constant in place instead of cloning and RAUWing it. - Make AbstractTypeUser a friend of Value so that it can offer its subclasses a way to update a Value's type in place. This is better than a universally visible setType method on Value, and it's sufficient for the immediate need. - Eliminate the constant "convert" functions. This eliminates a lot of logic duplication, and fixes a complicated bug where a constant can't actually be cloned during the type refinement process because some of the types that its folder needs are half-destroyed, being in the middle of refinement themselves. - Move the getValType functions from being static overloaded functions in Constants.cpp to be members of class template specializations in ConstantsContext.h. This means that the code ends up getting instantiated twice, however it also makes it possible to eliminate all "convert" functions, so it's not a big net code size increase. And if desired, the duplicate instantiations could be eliminated with some reorganization. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@81861 91177308-0d34-0410-b5e6-96231b3b80d8 Dan Gohman 11 years ago
7 changed file(s) with 209 addition(s) and 215 deletion(s). Raw diff Collapse all Expand all
3030
3131 namespace llvm {
3232
33 class Value;
3334 class Type;
3435 class DerivedType;
3536 template struct simplify_type;
5455 class AbstractTypeUser {
5556 protected:
5657 virtual ~AbstractTypeUser(); // Derive from me
58
59 /// setType - It's normally not possible to change a Value's type in place,
60 /// but an AbstractTypeUser subclass that knows what its doing can be
61 /// permitted to do so with care.
62 void setType(Value *V, const Type *NewTy);
63
5764 public:
5865
5966 /// refineAbstractType - The callback method invoked when an abstract type is
8080 friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name.
8181 friend class SymbolTable; // Allow SymbolTable to directly poke Name.
8282 friend class ValueHandleBase;
83 friend class AbstractTypeUser;
8384 ValueName *Name;
8485
8586 void operator=(const Value &); // Do not implement
877877 //===----------------------------------------------------------------------===//
878878 // Factory Function Implementation
879879
880 static char getValType(ConstantAggregateZero *CPZ) { return 0; }
881
882880 ConstantAggregateZero* ConstantAggregateZero::get(const Type* Ty) {
883881 assert((isa(Ty) || isa(Ty) || isa(Ty)) &&
884882 "Cannot create an aggregate zero of non-aggregate type!");
10071005 //---- ConstantPointerNull::get() implementation...
10081006 //
10091007
1010 static char getValType(ConstantPointerNull *) {
1011 return 0;
1012 }
1013
1014
10151008 ConstantPointerNull *ConstantPointerNull::get(const PointerType *Ty) {
10161009 // Implicitly locked.
10171010 return Ty->getContext().pImpl->NullPtrConstants.getOrCreate(Ty, 0);
10291022 //---- UndefValue::get() implementation...
10301023 //
10311024
1032 static char getValType(UndefValue *) {
1033 return 0;
1034 }
1035
10361025 UndefValue *UndefValue::get(const Type *Ty) {
10371026 // Implicitly locked.
10381027 return Ty->getContext().pImpl->UndefValueConstants.getOrCreate(Ty, 0);
10481037
10491038 //---- ConstantExpr::get() implementations...
10501039 //
1051
1052 static ExprMapKeyType getValType(ConstantExpr *CE) {
1053 std::vector Operands;
1054 Operands.reserve(CE->getNumOperands());
1055 for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
1056 Operands.push_back(cast(CE->getOperand(i)));
1057 return ExprMapKeyType(CE->getOpcode(), Operands,
1058 CE->isCompare() ? CE->getPredicate() : 0,
1059 CE->getRawSubclassOptionalData(),
1060 CE->hasIndices() ?
1061 CE->getIndices() : SmallVector());
1062 }
10631040
10641041 /// This is a utility function to handle folding of casts and lookup of the
10651042 /// cast in the ExprConstants map. It is used by the various get* methods below.
18771854 /// work, but would be really slow because it would have to unique each updated
18781855 /// array instance.
18791856
1880 static std::vector getValType(ConstantArray *CA) {
1881 std::vector Elements;
1882 Elements.reserve(CA->getNumOperands());
1883 for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
1884 Elements.push_back(cast(CA->getOperand(i)));
1885 return Elements;
1886 }
1887
1888
18891857 void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
18901858 Use *U) {
18911859 assert(isa(To) && "Cannot make Constant refer to non-constant!");
18941862 LLVMContext &Context = getType()->getContext();
18951863 LLVMContextImpl *pImpl = Context.pImpl;
18961864
1897 std::pair*> Lookup;
1865 std::pairArray*> Lookup;
18981866 Lookup.first.first = getType();
18991867 Lookup.second = this;
19001868
19721940 destroyConstant();
19731941 }
19741942
1975 static std::vector getValType(ConstantStruct *CS) {
1976 std::vector Elements;
1977 Elements.reserve(CS->getNumOperands());
1978 for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i)
1979 Elements.push_back(cast(CS->getOperand(i)));
1980 return Elements;
1981 }
1982
19831943 void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
19841944 Use *U) {
19851945 assert(isa(To) && "Cannot make Constant refer to non-constant!");
19881948 unsigned OperandToUpdate = U-OperandList;
19891949 assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
19901950
1991 std::pair*> Lookup;
1951 std::pairStruct*> Lookup;
19921952 Lookup.first.first = getType();
19931953 Lookup.second = this;
19941954 std::vector &Values = Lookup.first.second;
20462006
20472007 // Delete the old constant!
20482008 destroyConstant();
2049 }
2050
2051 static std::vector getValType(ConstantVector *CP) {
2052 std::vector Elements;
2053 Elements.reserve(CP->getNumOperands());
2054 for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
2055 Elements.push_back(CP->getOperand(i));
2056 return Elements;
20572009 }
20582010
20592011 void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To,
349349 }
350350 };
351351
352 template
353 struct ConvertConstantType {
354 static void convert(ConstantClass *OldC, const TypeClass *NewTy) {
355 llvm_unreachable("This type cannot be converted!");
352 template
353 struct ConstantKeyData {
354 typedef void ValType;
355 static ValType getValType(ConstantClass *C) {
356 llvm_unreachable("Unknown Constant type!");
356357 }
357358 };
358359
403404 };
404405
405406 template<>
406 struct ConvertConstantType {
407 static void convert(ConstantExpr *OldC, const Type *NewTy) {
408 Constant *New;
409 switch (OldC->getOpcode()) {
410 case Instruction::Trunc:
411 case Instruction::ZExt:
412 case Instruction::SExt:
413 case Instruction::FPTrunc:
414 case Instruction::FPExt:
415 case Instruction::UIToFP:
416 case Instruction::SIToFP:
417 case Instruction::FPToUI:
418 case Instruction::FPToSI:
419 case Instruction::PtrToInt:
420 case Instruction::IntToPtr:
421 case Instruction::BitCast:
422 New = ConstantExpr::getCast(OldC->getOpcode(), OldC->getOperand(0),
423 NewTy);
424 break;
425 case Instruction::Select:
426 New = ConstantExpr::getSelectTy(NewTy, OldC->getOperand(0),
427 OldC->getOperand(1),
428 OldC->getOperand(2));
429 break;
430 default:
431 assert(OldC->getOpcode() >= Instruction::BinaryOpsBegin &&
432 OldC->getOpcode() < Instruction::BinaryOpsEnd);
433 New = ConstantExpr::getTy(NewTy, OldC->getOpcode(), OldC->getOperand(0),
434 OldC->getOperand(1));
435 break;
436 case Instruction::GetElementPtr:
437 // Make everyone now use a constant of the new type...
438 std::vector Idx(OldC->op_begin()+1, OldC->op_end());
439 New = cast(OldC)->isInBounds() ?
440 ConstantExpr::getInBoundsGetElementPtrTy(NewTy, OldC->getOperand(0),
441 &Idx[0], Idx.size()) :
442 ConstantExpr::getGetElementPtrTy(NewTy, OldC->getOperand(0),
443 &Idx[0], Idx.size());
444 break;
445 }
446
447 assert(New != OldC && "Didn't replace constant??");
448 OldC->uncheckedReplaceAllUsesWith(New);
449 OldC->destroyConstant(); // This constant is now dead, destroy it.
407 struct ConstantKeyData {
408 typedef ExprMapKeyType ValType;
409 static ValType getValType(ConstantExpr *CE) {
410 std::vector Operands;
411 Operands.reserve(CE->getNumOperands());
412 for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
413 Operands.push_back(cast(CE->getOperand(i)));
414 return ExprMapKeyType(CE->getOpcode(), Operands,
415 CE->isCompare() ? CE->getPredicate() : 0,
416 CE->getRawSubclassOptionalData(),
417 CE->hasIndices() ?
418 CE->getIndices() : SmallVector());
450419 }
451420 };
452421
459428 };
460429
461430 template<>
462 struct ConvertConstantType {
463 static void convert(ConstantVector *OldC, const VectorType *NewTy) {
464 // Make everyone now use a constant of the new type...
465 std::vector C;
466 for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i)
467 C.push_back(cast(OldC->getOperand(i)));
468 Constant *New = ConstantVector::get(NewTy, C);
469 assert(New != OldC && "Didn't replace constant??");
470 OldC->uncheckedReplaceAllUsesWith(New);
471 OldC->destroyConstant(); // This constant is now dead, destroy it.
431 struct ConstantKeyData {
432 typedef std::vector ValType;
433 static ValType getValType(ConstantVector *CP) {
434 std::vector Elements;
435 Elements.reserve(CP->getNumOperands());
436 for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
437 Elements.push_back(CP->getOperand(i));
438 return Elements;
472439 }
473440 };
474441
475442 template<>
476 struct ConvertConstantType {
477 static void convert(ConstantAggregateZero *OldC, const Type *NewTy) {
478 // Make everyone now use a constant of the new type...
479 Constant *New = ConstantAggregateZero::get(NewTy);
480 assert(New != OldC && "Didn't replace constant??");
481 OldC->uncheckedReplaceAllUsesWith(New);
482 OldC->destroyConstant(); // This constant is now dead, destroy it.
443 struct ConstantKeyData {
444 typedef char ValType;
445 static ValType getValType(ConstantAggregateZero *C) {
446 return 0;
483447 }
484448 };
485449
486450 template<>
487 struct ConvertConstantType {
488 static void convert(ConstantArray *OldC, const ArrayType *NewTy) {
489 // Make everyone now use a constant of the new type...
490 std::vector C;
491 for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i)
492 C.push_back(cast(OldC->getOperand(i)));
493 Constant *New = ConstantArray::get(NewTy, C);
494 assert(New != OldC && "Didn't replace constant??");
495 OldC->uncheckedReplaceAllUsesWith(New);
496 OldC->destroyConstant(); // This constant is now dead, destroy it.
451 struct ConstantKeyData {
452 typedef std::vector ValType;
453 static ValType getValType(ConstantArray *CA) {
454 std::vector Elements;
455 Elements.reserve(CA->getNumOperands());
456 for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
457 Elements.push_back(cast(CA->getOperand(i)));
458 return Elements;
497459 }
498460 };
499461
500462 template<>
501 struct ConvertConstantType {
502 static void convert(ConstantStruct *OldC, const StructType *NewTy) {
503 // Make everyone now use a constant of the new type...
504 std::vector C;
505 for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i)
506 C.push_back(cast(OldC->getOperand(i)));
507 Constant *New = ConstantStruct::get(NewTy, C);
508 assert(New != OldC && "Didn't replace constant??");
509
510 OldC->uncheckedReplaceAllUsesWith(New);
511 OldC->destroyConstant(); // This constant is now dead, destroy it.
463 struct ConstantKeyData {
464 typedef std::vector ValType;
465 static ValType getValType(ConstantStruct *CS) {
466 std::vector Elements;
467 Elements.reserve(CS->getNumOperands());
468 for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i)
469 Elements.push_back(cast(CS->getOperand(i)));
470 return Elements;
512471 }
513472 };
514473
521480 };
522481
523482 template<>
524 struct ConvertConstantType {
525 static void convert(ConstantPointerNull *OldC, const PointerType *NewTy) {
526 // Make everyone now use a constant of the new type...
527 Constant *New = ConstantPointerNull::get(NewTy);
528 assert(New != OldC && "Didn't replace constant??");
529 OldC->uncheckedReplaceAllUsesWith(New);
530 OldC->destroyConstant(); // This constant is now dead, destroy it.
483 struct ConstantKeyData {
484 typedef char ValType;
485 static ValType getValType(ConstantPointerNull *C) {
486 return 0;
531487 }
532488 };
533489
540496 };
541497
542498 template<>
543 struct ConvertConstantType {
544 static void convert(UndefValue *OldC, const Type *NewTy) {
545 // Make everyone now use a constant of the new type.
546 Constant *New = UndefValue::get(NewTy);
547 assert(New != OldC && "Didn't replace constant??");
548 OldC->uncheckedReplaceAllUsesWith(New);
549 OldC->destroyConstant(); // This constant is now dead, destroy it.
499 struct ConstantKeyData {
500 typedef char ValType;
501 static ValType getValType(UndefValue *C) {
502 return 0;
550503 }
551504 };
552505
554507 bool HasLargeKey = false /*true for arrays and structs*/ >
555508 class ValueMap : public AbstractTypeUser {
556509 public:
557 typedef std::pair MapKey;
558 typedef std::map MapTy;
559 typedef std::map InverseMapTy;
560 typedef std::map AbstractTypeMapTy;
510 typedef std::pair MapKey;
511 typedef std::map MapTy;
512 typedef std::map InverseMapTy;
513 typedef std::map
514 AbstractTypeMapTy;
561515 private:
562516 /// Map - This is the main map from the element descriptor to the Constants.
563517 /// This is the primary way we avoid creating two of the same shape
598552 /// I->second == 0, and should be filled in.
599553 /// NOTE: This function is not locked. It is the caller's responsibility
600554 // to enforce proper synchronization.
601 typename MapTy::iterator InsertOrGetItem(std::pair *>
555 typename MapTy::iterator InsertOrGetItem(std::pairClass *>
602556 &InsertVal,
603557 bool &Exists) {
604558 std::pair IP = Map.insert(InsertVal);
618572
619573 typename MapTy::iterator I =
620574 Map.find(MapKey(static_cast(CP->getRawType()),
621 getValType(CP)));
575 ConstantKeyData::getValType(CP)));
622576 if (I == Map.end() || I->second != CP) {
623577 // FIXME: This should not use a linear scan. If this gets to be a
624578 // performance problem, someone should look at this.
628582 return I;
629583 }
630584
585 void AddAbstractTypeUser(const Type *Ty, typename MapTy::iterator I) {
586 // If the type of the constant is abstract, make sure that an entry
587 // exists for it in the AbstractTypeMap.
588 if (Ty->isAbstract()) {
589 const DerivedType *DTy = static_cast(Ty);
590 typename AbstractTypeMapTy::iterator TI = AbstractTypeMap.find(DTy);
591
592 if (TI == AbstractTypeMap.end()) {
593 // Add ourselves to the ATU list of the type.
594 cast(DTy)->addAbstractTypeUser(this);
595
596 AbstractTypeMap.insert(TI, std::make_pair(DTy, I));
597 }
598 }
599 }
600
631601 ConstantClass* Create(const TypeClass *Ty, const ValType &V,
632602 typename MapTy::iterator I) {
633603 ConstantClass* Result =
639609 if (HasLargeKey) // Remember the reverse mapping if needed.
640610 InverseMap.insert(std::make_pair(Result, I));
641611
642 // If the type of the constant is abstract, make sure that an entry
643 // exists for it in the AbstractTypeMap.
644 if (Ty->isAbstract()) {
645 typename AbstractTypeMapTy::iterator TI =
646 AbstractTypeMap.find(Ty);
647
648 if (TI == AbstractTypeMap.end()) {
649 // Add ourselves to the ATU list of the type.
650 cast(Ty)->addAbstractTypeUser(this);
651
652 AbstractTypeMap.insert(TI, std::make_pair(Ty, I));
653 }
654 }
612 AddAbstractTypeUser(Ty, I);
655613
656614 return Result;
657615 }
667625 typename MapTy::iterator I = Map.find(Lookup);
668626 // Is it in the map?
669627 if (I != Map.end())
670 Result = static_cast(I->second);
628 Result = I->second;
671629
672630 if (!Result) {
673631 // If no preexisting value, create one now...
675633 }
676634
677635 return Result;
636 }
637
638 void UpdateAbstractTypeMap(const DerivedType *Ty,
639 typename MapTy::iterator I) {
640 assert(AbstractTypeMap.count(Ty) &&
641 "Abstract type not in AbstractTypeMap?");
642 typename MapTy::iterator &ATMEntryIt = AbstractTypeMap[Ty];
643 if (ATMEntryIt == I) {
644 // Yes, we are removing the representative entry for this type.
645 // See if there are any other entries of the same type.
646 typename MapTy::iterator TmpIt = ATMEntryIt;
647
648 // First check the entry before this one...
649 if (TmpIt != Map.begin()) {
650 --TmpIt;
651 if (TmpIt->first.first != Ty) // Not the same type, move back...
652 ++TmpIt;
653 }
654
655 // If we didn't find the same type, try to move forward...
656 if (TmpIt == ATMEntryIt) {
657 ++TmpIt;
658 if (TmpIt == Map.end() || TmpIt->first.first != Ty)
659 --TmpIt; // No entry afterwards with the same type
660 }
661
662 // If there is another entry in the map of the same abstract type,
663 // update the AbstractTypeMap entry now.
664 if (TmpIt != ATMEntryIt) {
665 ATMEntryIt = TmpIt;
666 } else {
667 // Otherwise, we are removing the last instance of this type
668 // from the table. Remove from the ATM, and from user list.
669 cast(Ty)->removeAbstractTypeUser(this);
670 AbstractTypeMap.erase(Ty);
671 }
672 }
678673 }
679674
680675 void remove(ConstantClass *CP) {
688683
689684 // Now that we found the entry, make sure this isn't the entry that
690685 // the AbstractTypeMap points to.
691 const TypeClass *Ty = static_cast(I->first.first);
692 if (Ty->isAbstract()) {
693 assert(AbstractTypeMap.count(Ty) &&
694 "Abstract type not in AbstractTypeMap?");
695 typename MapTy::iterator &ATMEntryIt = AbstractTypeMap[Ty];
696 if (ATMEntryIt == I) {
697 // Yes, we are removing the representative entry for this type.
698 // See if there are any other entries of the same type.
699 typename MapTy::iterator TmpIt = ATMEntryIt;
700
701 // First check the entry before this one...
702 if (TmpIt != Map.begin()) {
703 --TmpIt;
704 if (TmpIt->first.first != Ty) // Not the same type, move back...
705 ++TmpIt;
706 }
707
708 // If we didn't find the same type, try to move forward...
709 if (TmpIt == ATMEntryIt) {
710 ++TmpIt;
711 if (TmpIt == Map.end() || TmpIt->first.first != Ty)
712 --TmpIt; // No entry afterwards with the same type
713 }
714
715 // If there is another entry in the map of the same abstract type,
716 // update the AbstractTypeMap entry now.
717 if (TmpIt != ATMEntryIt) {
718 ATMEntryIt = TmpIt;
719 } else {
720 // Otherwise, we are removing the last instance of this type
721 // from the table. Remove from the ATM, and from user list.
722 cast(Ty)->removeAbstractTypeUser(this);
723 AbstractTypeMap.erase(Ty);
724 }
725 }
726 }
686 const TypeClass *Ty = I->first.first;
687 if (Ty->isAbstract())
688 UpdateAbstractTypeMap(static_cast(Ty), I);
727689
728690 Map.erase(I);
729691 }
730692
731
732693 /// MoveConstantToNewSlot - If we are about to change C to be the element
733694 /// specified by I, update our internal data structures to reflect this
734695 /// fact.
764725
765726 void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
766727 sys::SmartScopedLock Lock(ValueMapLock);
767 typename AbstractTypeMapTy::iterator I =
768 AbstractTypeMap.find(cast(OldTy));
728 typename AbstractTypeMapTy::iterator I = AbstractTypeMap.find(OldTy);
769729
770730 assert(I != AbstractTypeMap.end() &&
771731 "Abstract type not in AbstractTypeMap?");
774734 // leaving will remove() itself, causing the AbstractTypeMapEntry to be
775735 // eliminated eventually.
776736 do {
777 ConvertConstantType
778 TypeClass>::convert(
779 static_cast(I->second->second),
780 cast(NewTy));
781
782 I = AbstractTypeMap.find(cast(OldTy));
737 ConstantClass *C = I->second->second;
738 MapKey Key(cast(NewTy),
739 ConstantKeyData::getValType(C));
740
741 std::pair IP =
742 Map.insert(std::make_pair(Key, C));
743 if (IP.second) {
744 // The map didn't previously have an appropriate constant in the
745 // new type.
746
747 // Remove the old entry.
748 typename MapTy::iterator OldI =
749 Map.find(MapKey(cast(OldTy), IP.first->first.second));
750 assert(OldI != Map.end() && "Constant not in map!");
751 UpdateAbstractTypeMap(OldTy, OldI);
752 Map.erase(OldI);
753
754 // Set the constant's type. This is done in place!
755 setType(C, NewTy);
756
757 // Update the inverse map so that we know that this constant is now
758 // located at descriptor I.
759 if (HasLargeKey)
760 InverseMap[C] = IP.first;
761
762 AddAbstractTypeUser(NewTy, IP.first);
763 } else {
764 // The map already had an appropriate constant in the new type, so
765 // there's no longer a need for the old constant.
766 C->uncheckedReplaceAllUsesWith(IP.first->second);
767 C->destroyConstant(); // This constant is now dead, destroy it.
768 }
769 I = AbstractTypeMap.find(OldTy);
783770 } while (I != AbstractTypeMap.end());
784771 }
785772
4141
4242 AbstractTypeUser::~AbstractTypeUser() {}
4343
44 void AbstractTypeUser::setType(Value *V, const Type *NewTy) {
45 V->VTy = NewTy;
46 }
4447
4548 //===----------------------------------------------------------------------===//
4649 // Type Class Implementation
0 ; This file is used by first.ll, so it doesn't actually do anything itself
1 ; RUN: true
2
3 %AnalysisResolver = type { i8, %PMDataManager* }
4 %"DenseMap" = type { i64, %"pair"*, i64, i64 }
5 %PMDataManager = type { i8, %PMTopLevelManager*, i8, i8, i8, i8, i8, i64, i8 }
6 %PMTopLevelManager = type { i8, i8, i8, i8, i8, i8, i8, i8, %"DenseMap" }
7 %P = type { i8, %AnalysisResolver*, i64 }
8 %PI = type { i8, i8, i8, i8, i8, i8, %"vector", %P* }
9 %"SmallVImpl" = type { i8, %PI* }
10 %"_V_base" = type { %"_V_base::_V_impl" }
11 %"_V_base::_V_impl" = type { %PI*, i8, i8 }
12 %"pair" = type opaque
13 %"vector" = type { %"_V_base" }
14
15 define void @f(%"SmallVImpl"* %this) {
16 entry:
17 %x = getelementptr inbounds %"SmallVImpl"* %this, i64 0, i32 1
18 ret void
19 }
0 ; RUN: llvm-link %s %p/partial-type-refinement-link.ll -S | FileCheck %s
1 ; PR4954
2
3 ; CHECK: load %PI** getelementptr inbounds (%"RegisterP"* @_ZN3mvmL1XE, i64 0, i32 0, i32 6, i32 0, i32 0, i32 0), align 16
4
5 %AnalysisResolver = type { i8, %PMDataManager* }
6 %"DenseMap" = type { i64, %"pair"*, i64, i64 }
7 %PMDataManager = type { i8, %PMTopLevelManager*, i8, i8, i8, i8, i8, i64, i8 }
8 %PMTopLevelManager = type { i8, i8, i8, i8, i8, i8, i8, i8, %"DenseMap" }
9 %P = type { i8, %AnalysisResolver*, i64 }
10 %PI = type { i8, i8, i8, i8, i8, i8, %"vector", %P* }
11 %"RegisterP" = type { %PI }
12 %"_V_base" = type { %"_V_base::_V_impl" }
13 %"_V_base::_V_impl" = type { %PI*, i8, i8 }
14 %"pair" = type opaque
15 %"vector" = type { %"_V_base" }
16
17 @_ZN3mvmL1XE = external global %"RegisterP"
18
19 define void @__tcf_0() nounwind {
20 entry:
21 %0 = load %PI** getelementptr inbounds (%"RegisterP"* @_ZN3mvmL1XE, i64 0, i32 0, i32 6, i32 0, i32 0, i32 0), align 16
22 ret void
23 }