Index: llvm/trunk/include/llvm/IR/Attributes.h =================================================================== --- llvm/trunk/include/llvm/IR/Attributes.h +++ llvm/trunk/include/llvm/IR/Attributes.h @@ -511,6 +511,9 @@ /// \brief Return the attributes at the given slot. AttributeList getSlotAttributes(unsigned Slot) const; + /// \brief Return the attributes at the given slot. + AttributeSet getSlotSet(unsigned Slot) const; + void dump() const; }; Index: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -726,54 +726,50 @@ } void ModuleBitcodeWriter::writeAttributeGroupTable() { - const std::vector &AttrGrps = VE.getAttributeGroups(); + const std::vector &AttrGrps = + VE.getAttributeGroups(); if (AttrGrps.empty()) return; Stream.EnterSubblock(bitc::PARAMATTR_GROUP_BLOCK_ID, 3); SmallVector Record; - for (unsigned i = 0, e = AttrGrps.size(); i != e; ++i) { - AttributeList AS = AttrGrps[i]; - for (unsigned i = 0, e = AS.getNumSlots(); i != e; ++i) { - AttributeList A = AS.getSlotAttributes(i); - - Record.push_back(VE.getAttributeGroupID(A)); - Record.push_back(AS.getSlotIndex(i)); - - for (AttributeList::iterator I = AS.begin(0), E = AS.end(0); I != E; - ++I) { - Attribute Attr = *I; - if (Attr.isEnumAttribute()) { - Record.push_back(0); - Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); - } else if (Attr.isIntAttribute()) { - Record.push_back(1); - Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); - Record.push_back(Attr.getValueAsInt()); - } else { - StringRef Kind = Attr.getKindAsString(); - StringRef Val = Attr.getValueAsString(); + for (ValueEnumerator::IndexAndAttrSet Pair : AttrGrps) { + unsigned AttrListIndex = Pair.first; + AttributeSet AS = Pair.second; + Record.push_back(VE.getAttributeGroupID(Pair)); + Record.push_back(AttrListIndex); + + for (Attribute Attr : AS) { + if (Attr.isEnumAttribute()) { + Record.push_back(0); + Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); + } else if (Attr.isIntAttribute()) { + Record.push_back(1); + Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); + Record.push_back(Attr.getValueAsInt()); + } else { + StringRef Kind = Attr.getKindAsString(); + StringRef Val = Attr.getValueAsString(); - Record.push_back(Val.empty() ? 3 : 4); - Record.append(Kind.begin(), Kind.end()); + Record.push_back(Val.empty() ? 3 : 4); + Record.append(Kind.begin(), Kind.end()); + Record.push_back(0); + if (!Val.empty()) { + Record.append(Val.begin(), Val.end()); Record.push_back(0); - if (!Val.empty()) { - Record.append(Val.begin(), Val.end()); - Record.push_back(0); - } } } - - Stream.EmitRecord(bitc::PARAMATTR_GRP_CODE_ENTRY, Record); - Record.clear(); } + + Stream.EmitRecord(bitc::PARAMATTR_GRP_CODE_ENTRY, Record); + Record.clear(); } Stream.ExitBlock(); } void ModuleBitcodeWriter::writeAttributeTable() { - const std::vector &Attrs = VE.getAttributes(); + const std::vector &Attrs = VE.getAttributeLists(); if (Attrs.empty()) return; Stream.EnterSubblock(bitc::PARAMATTR_BLOCK_ID, 3); @@ -782,7 +778,8 @@ for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { const AttributeList &A = Attrs[i]; for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i) - Record.push_back(VE.getAttributeGroupID(A.getSlotAttributes(i))); + Record.push_back( + VE.getAttributeGroupID({A.getSlotIndex(i), A.getSlotSet(i)})); Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record); Record.clear(); @@ -1270,7 +1267,7 @@ Vals.push_back(F.getCallingConv()); Vals.push_back(F.isDeclaration()); Vals.push_back(getEncodedLinkage(F)); - Vals.push_back(VE.getAttributeID(F.getAttributes())); + Vals.push_back(VE.getAttributeListID(F.getAttributes())); Vals.push_back(Log2_32(F.getAlignment())+1); Vals.push_back(F.hasSection() ? SectionMap[F.getSection()] : 0); Vals.push_back(getEncodedVisibility(F)); @@ -2616,7 +2613,7 @@ Code = bitc::FUNC_CODE_INST_INVOKE; - Vals.push_back(VE.getAttributeID(II->getAttributes())); + Vals.push_back(VE.getAttributeListID(II->getAttributes())); Vals.push_back(II->getCallingConv() | 1 << 13); Vals.push_back(VE.getValueID(II->getNormalDest())); Vals.push_back(VE.getValueID(II->getUnwindDest())); @@ -2808,7 +2805,7 @@ Code = bitc::FUNC_CODE_INST_CALL; - Vals.push_back(VE.getAttributeID(CI.getAttributes())); + Vals.push_back(VE.getAttributeListID(CI.getAttributes())); unsigned Flags = getOptimizationFlags(&I); Vals.push_back(CI.getCallingConv() << bitc::CALL_CCONV | Index: llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.h =================================================================== --- llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.h +++ llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.h @@ -48,6 +48,10 @@ // For each value, we remember its Value* and occurrence frequency. typedef std::vector > ValueList; + /// Attribute groups as encoded in bitcode are almost AttributeSets, but they + /// include the AttributeList index, so we have to track that in our map. + typedef std::pair IndexAndAttrSet; + UseListOrderStack UseListOrders; private: @@ -102,13 +106,13 @@ bool ShouldPreserveUseListOrder; - typedef DenseMap AttributeGroupMapType; + typedef DenseMap AttributeGroupMapType; AttributeGroupMapType AttributeGroupMap; - std::vector AttributeGroups; + std::vector AttributeGroups; - typedef DenseMap AttributeMapType; - AttributeMapType AttributeMap; - std::vector Attribute; + typedef DenseMap AttributeListMapType; + AttributeListMapType AttributeListMap; + std::vector AttributeLists; /// GlobalBasicBlockIDs - This map memoizes the basic block ID's referenced by /// the "getGlobalBasicBlockID" method. @@ -166,16 +170,17 @@ unsigned getInstructionID(const Instruction *I) const; void setInstructionID(const Instruction *I); - unsigned getAttributeID(AttributeList PAL) const { + unsigned getAttributeListID(AttributeList PAL) const { if (PAL.isEmpty()) return 0; // Null maps to zero. - AttributeMapType::const_iterator I = AttributeMap.find(PAL); - assert(I != AttributeMap.end() && "Attribute not in ValueEnumerator!"); + AttributeListMapType::const_iterator I = AttributeListMap.find(PAL); + assert(I != AttributeListMap.end() && "Attribute not in ValueEnumerator!"); return I->second; } - unsigned getAttributeGroupID(AttributeList PAL) const { - if (PAL.isEmpty()) return 0; // Null maps to zero. - AttributeGroupMapType::const_iterator I = AttributeGroupMap.find(PAL); + unsigned getAttributeGroupID(IndexAndAttrSet Group) const { + if (!Group.second.hasAttributes()) + return 0; // Null maps to zero. + AttributeGroupMapType::const_iterator I = AttributeGroupMap.find(Group); assert(I != AttributeGroupMap.end() && "Attribute not in ValueEnumerator!"); return I->second; } @@ -206,8 +211,8 @@ const std::vector &getBasicBlocks() const { return BasicBlocks; } - const std::vector &getAttributes() const { return Attribute; } - const std::vector &getAttributeGroups() const { + const std::vector &getAttributeLists() const { return AttributeLists; } + const std::vector &getAttributeGroups() const { return AttributeGroups; } Index: llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp +++ llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -891,19 +891,19 @@ if (PAL.isEmpty()) return; // null is always 0. // Do a lookup. - unsigned &Entry = AttributeMap[PAL]; + unsigned &Entry = AttributeListMap[PAL]; if (Entry == 0) { // Never saw this before, add it. - Attribute.push_back(PAL); - Entry = Attribute.size(); + AttributeLists.push_back(PAL); + Entry = AttributeLists.size(); } // Do lookups for all attribute groups. for (unsigned i = 0, e = PAL.getNumSlots(); i != e; ++i) { - AttributeList AS = PAL.getSlotAttributes(i); - unsigned &Entry = AttributeGroupMap[AS]; + IndexAndAttrSet Pair = {PAL.getSlotIndex(i), PAL.getSlotSet(i)}; + unsigned &Entry = AttributeGroupMap[Pair]; if (Entry == 0) { - AttributeGroups.push_back(AS); + AttributeGroups.push_back(Pair); Entry = AttributeGroups.size(); } } Index: llvm/trunk/lib/IR/Attributes.cpp =================================================================== --- llvm/trunk/lib/IR/Attributes.cpp +++ llvm/trunk/lib/IR/Attributes.cpp @@ -1257,6 +1257,12 @@ return pImpl->getSlotAttributes(Slot); } +AttributeSet AttributeList::getSlotSet(unsigned Slot) const { + assert(pImpl && Slot < pImpl->getNumSlots() && + "Slot # out of range!"); + return pImpl->getSlotNode(Slot); +} + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void AttributeList::dump() const { dbgs() << "PAL[\n";