diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index ee9e11541206..a842bd3643d0 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -133,15 +133,6 @@ namespace { : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) { Op<0>() = UndefValue::get(Type::Int32Ty); } - - /// @brief Methods to support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const ConstantPlaceHolder *) { return true; } - static bool classof(const Value *V) { - return isa(V) && - cast(V)->getOpcode() == Instruction::UserOp1; - } - - /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); }; @@ -214,85 +205,6 @@ Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) { return V; } -/// ResolveConstantForwardRefs - Once all constants are read, this method bulk -/// resolves any forward references. The idea behind this is that we sometimes -/// get constants (such as large arrays) which reference *many* forward ref -/// constants. Replacing each of these causes a lot of thrashing when -/// building/reuniquing the constant. Instead of doing this, we look at all the -/// uses and rewrite all the place holders at once for any constant that uses -/// a placeholder. -void BitcodeReaderValueList::ResolveConstantForwardRefs() { - // Sort the values by-pointer so that they are efficient to look up with a - // binary search. - std::sort(ResolveConstants.begin(), ResolveConstants.end()); - - SmallVector NewOps; - - while (!ResolveConstants.empty()) { - Value *RealVal = getOperand(ResolveConstants.back().second); - Constant *Placeholder = ResolveConstants.back().first; - ResolveConstants.pop_back(); - - // Loop over all users of the placeholder, updating them to reference the - // new value. If they reference more than one placeholder, update them all - // at once. - while (!Placeholder->use_empty()) { - User *U = Placeholder->use_back(); - // If the using object isn't uniqued, just update the operands. This - // handles instructions and initializers for global variables. - if (!isa(U) || isa(U)) { - U->replaceUsesOfWith(Placeholder, RealVal); - continue; - } - - // Otherwise, we have a constant that uses the placeholder. Replace that - // constant with a new constant that has *all* placeholder uses updated. - Constant *UserC = cast(U); - for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end(); - I != E; ++I) { - Value *NewOp; - if (!isa(*I)) { - // Not a placeholder reference. - NewOp = *I; - } else if (*I == Placeholder) { - // Common case is that it just references this one placeholder. - NewOp = RealVal; - } else { - // Otherwise, look up the placeholder in ResolveConstants. - ResolveConstantsTy::iterator It = - std::lower_bound(ResolveConstants.begin(), ResolveConstants.end(), - std::pair(cast(*I), - 0)); - assert(It != ResolveConstants.end() && It->first == *I); - NewOp = this->getOperand(It->second); - } - - NewOps.push_back(cast(NewOp)); - } - - // Make the new constant. - Constant *NewC; - if (ConstantArray *UserCA = dyn_cast(UserC)) { - NewC = ConstantArray::get(UserCA->getType(), &NewOps[0], NewOps.size()); - } else if (isa(UserC)) { - NewC = ConstantStruct::get(&NewOps[0], NewOps.size()); - } else if (isa(UserC)) { - NewC = ConstantVector::get(&NewOps[0], NewOps.size()); - } else { - // Must be a constant expression. - NewC = cast(UserC)->getWithOperands(&NewOps[0], - NewOps.size()); - } - - UserC->replaceAllUsesWith(NewC); - UserC->destroyConstant(); - NewOps.clear(); - } - - delete Placeholder; - } -} - const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) { // If the TypeID is in range, return it. @@ -690,8 +602,14 @@ bool BitcodeReader::ParseConstants() { unsigned NextCstNo = ValueList.size(); while (1) { unsigned Code = Stream.ReadCode(); - if (Code == bitc::END_BLOCK) - break; + if (Code == bitc::END_BLOCK) { + if (NextCstNo != ValueList.size()) + return Error("Invalid constant reference!"); + + if (Stream.ReadBlockEnd()) + return Error("Error at end of constants block"); + return false; + } if (Code == bitc::ENTER_SUBBLOCK) { // No known subblocks, always skip them. @@ -934,17 +852,6 @@ bool BitcodeReader::ParseConstants() { ValueList.AssignValue(V, NextCstNo); ++NextCstNo; } - - if (NextCstNo != ValueList.size()) - return Error("Invalid constant reference!"); - - if (Stream.ReadBlockEnd()) - return Error("Error at end of constants block"); - - // Once all the constants have been read, go through and resolve forward - // references. - ValueList.ResolveConstantForwardRefs(); - return false; } /// RememberAndSkipFunctionBody - When we see the block for a function body, diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.h b/llvm/lib/Bitcode/Reader/BitcodeReader.h index 7bd05cfd2d28..9f62efec2932 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.h +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.h @@ -32,22 +32,9 @@ namespace llvm { class BitcodeReaderValueList : public User { unsigned Capacity; - - /// ResolveConstants - As we resolve forward-referenced constants, we add - /// information about them to this vector. This allows us to resolve them in - /// bulk instead of resolving each reference at a time. See the code in - /// ResolveConstantForwardRefs for more information about this. - /// - /// The key of this vector is the placeholder constant, the value is the slot - /// number that holds the resolved value. - typedef std::vector > ResolveConstantsTy; - ResolveConstantsTy ResolveConstants; public: BitcodeReaderValueList() : User(Type::VoidTy, Value::ArgumentVal, 0, 0) , Capacity(0) {} - ~BitcodeReaderValueList() { - assert(ResolveConstants.empty() && "Constants not resolved?"); - } /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -63,7 +50,6 @@ public: } void clear() { - assert(ResolveConstants.empty() && "Constants not resolved?"); if (OperandList) dropHungoffUses(OperandList); Capacity = 0; } @@ -87,26 +73,15 @@ public: if (Idx == size()) { push_back(V); } else if (Value *OldV = getOperand(Idx)) { - // Handle constants and non-constants (e.g. instrs) differently for - // efficiency. - if (Constant *PHC = dyn_cast(OldV)) { - ResolveConstants.push_back(std::make_pair(PHC, Idx)); - setOperand(Idx, V); - } else { - // If there was a forward reference to this value, replace it. - setOperand(Idx, V); - OldV->replaceAllUsesWith(V); - delete OldV; - } + // If there was a forward reference to this value, replace it. + setOperand(Idx, V); + OldV->replaceAllUsesWith(V); + delete OldV; } else { initVal(Idx, V); } } - /// ResolveConstantForwardRefs - Once all constants are read, this method bulk - /// resolves any forward references. - void ResolveConstantForwardRefs(); - private: void initVal(unsigned Idx, Value *V) { if (Idx >= size()) { @@ -119,8 +94,7 @@ private: }; template <> -struct OperandTraits - : HungoffOperandTraits { +struct OperandTraits : HungoffOperandTraits { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BitcodeReaderValueList, Value)