Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2353,6 +2353,16 @@ unsigned CstNo; }; std::vector DelayedShuffles; + struct DelayedSelTy { + Type *OpTy; + Type *SelectorTy; + uint64_t Op0Idx; + uint64_t Op1Idx; + uint64_t Op2Idx; + unsigned CstNo; + }; + std::vector DelayedSelectors; + while (true) { Expected MaybeEntry = Stream.advanceSkippingSubblocks(); if (!MaybeEntry) @@ -2363,7 +2373,7 @@ case BitstreamEntry::SubBlock: // Handled for us already. case BitstreamEntry::Error: return error("Malformed block"); - case BitstreamEntry::EndBlock: + case BitstreamEntry::EndBlock: { // Once all the constants have been read, go through and resolve forward // references. // @@ -2389,12 +2399,45 @@ Value *V = ConstantExpr::getShuffleVector(Op0, Op1, Mask); ValueList.assignValue(V, CstNo); } + std::vector DelayedSelectorsSet(DelayedSelectors.size(), 1); + while (true) { + for (size_t i = 0; i < DelayedSelectors.size(); ++i) { + auto &DelayedSelector = DelayedSelectors[i]; + Type *OpTy = DelayedSelector.OpTy; + Type *SelectorTy = DelayedSelector.SelectorTy; + uint64_t Op0Idx = DelayedSelector.Op0Idx; + uint64_t Op1Idx = DelayedSelector.Op1Idx; + uint64_t Op2Idx = DelayedSelector.Op2Idx; + uint64_t CstNo = DelayedSelector.CstNo; + Constant *Op1 = ValueList.getConstantFwdRef(Op1Idx, OpTy); + Constant *Op2 = ValueList.getConstantFwdRef(Op2Idx, OpTy); + // The selector might be an i1 or an + // Get the type from the ValueList before getting a forward ref. + if (VectorType *VTy = dyn_cast(OpTy)) + if (Value *V = ValueList[Op0Idx]) { + DelayedSelectorsSet[i] = 0; + if (SelectorTy != V->getType()) + SelectorTy = + VectorType::get(SelectorTy, VTy->getElementCount()); + } else { + continue; + } + Constant *Op0 = ValueList.getConstantFwdRef(Op0Idx, SelectorTy); + Value *V = ConstantExpr::getSelect(Op0, Op1, Op2); + ValueList.assignValue(V, CstNo); + } + if (all_of(DelayedSelectorsSet.begin(), DelayedSelectorsSet.end(), + [](int i) { return i == 0; })) { + break; + } + } if (NextCstNo != ValueList.size()) return error("Invalid constant reference"); ValueList.resolveConstantForwardRefs(); return Error::success(); + } case BitstreamEntry::Record: // The interesting case. break; @@ -2686,20 +2729,10 @@ return error("Invalid record"); Type *SelectorTy = Type::getInt1Ty(Context); - - // The selector might be an i1, an , or a - // Get the type from the ValueList before getting a forward ref. - if (VectorType *VTy = dyn_cast(CurTy)) - if (Value *V = ValueList[Record[0]]) - if (SelectorTy != V->getType()) - SelectorTy = VectorType::get(SelectorTy, - VTy->getElementCount()); - - V = ConstantExpr::getSelect(ValueList.getConstantFwdRef(Record[0], - SelectorTy), - ValueList.getConstantFwdRef(Record[1],CurTy), - ValueList.getConstantFwdRef(Record[2],CurTy)); - break; + DelayedSelectors.push_back({CurTy, SelectorTy, Record[0], Record[1], + Record[2], NextCstNo}); + ++NextCstNo; + continue; } case bitc::CST_CODE_CE_EXTRACTELT : { // CE_EXTRACTELT: [opty, opval, opty, opval] Index: llvm/lib/Bitcode/Reader/ValueList.cpp =================================================================== --- llvm/lib/Bitcode/Reader/ValueList.cpp +++ llvm/lib/Bitcode/Reader/ValueList.cpp @@ -152,7 +152,8 @@ Value *RealVal = operator[](ResolveConstants.back().second); Constant *Placeholder = ResolveConstants.back().first; ResolveConstants.pop_back(); - + if (Placeholder == RealVal) + continue; // 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. Index: llvm/test/Bitcode/bitcode-parseconstant-delay-select.ll =================================================================== --- /dev/null +++ llvm/test/Bitcode/bitcode-parseconstant-delay-select.ll @@ -0,0 +1,13 @@ +; RUN: llvm-as < %s -preserve-bc-uselistorder=false | llvm-dis -disable-output +@a = external dso_local global i32, align 4 +@c = external dso_local global [3 x i32], align 4 +@b = external dso_local local_unnamed_addr global i32, align 4 + +define dso_local i32 @main() local_unnamed_addr { +middle.block: + br label %for.cond.for.end_crit_edge + +for.cond.for.end_crit_edge: ; preds = %middle.block + store i32 extractelement (<4 x i32> select (<4 x i1> select (<4 x i1> , <4 x i1> , <4 x i1> zeroinitializer), <4 x i32> zeroinitializer, <4 x i32> select (<4 x i1> select (<4 x i1> , <4 x i1> , <4 x i1> zeroinitializer), <4 x i32> , <4 x i32> )), i32 3), i32* @b, align 4 + ret i32 undef +}