diff --git a/emscripten-version.txt b/emscripten-version.txt index b4b5f1baed1..2a788d314ba 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1 +1 @@ -"1.37.9" +"1.37.10" diff --git a/lib/Target/JSBackend/NaCl/ExpandStructRegs.cpp b/lib/Target/JSBackend/NaCl/ExpandStructRegs.cpp index 4922a38308e..ca1fb9db5da 100644 --- a/lib/Target/JSBackend/NaCl/ExpandStructRegs.cpp +++ b/lib/Target/JSBackend/NaCl/ExpandStructRegs.cpp @@ -68,7 +68,9 @@ char ExpandStructRegs::ID = 0; INITIALIZE_PASS(ExpandStructRegs, "expand-struct-regs", "Expand out variables with struct types", false, false) -static bool DoAnotherPass(Type *Ty) { return isa(Ty); } +static bool DoAnotherPass(Type *Ty) { + return isa(Ty) || isa(Ty); +} static bool DoAnotherPass(Value *V) { return DoAnotherPass(V->getType()); } static bool SplitUpPHINode(PHINode *Phi) { @@ -257,7 +259,7 @@ static bool SplitUpArrayStore(StoreInst *Store, const DataLayout *DL) { ArrayType *ATy = cast(Store->getValueOperand()->getType()); bool NeedsAnotherPass = false; - // Create a separate store instruction for each struct field. + // Create a separate store instruction for each array field. for (unsigned Index = 0; Index < ATy->getNumElements(); ++Index) { SmallVector Indexes; Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, 0))); @@ -285,10 +287,10 @@ static bool SplitUpArrayStore(StoreInst *Store, const DataLayout *DL) { static bool SplitUpArrayLoad(LoadInst *Load, const DataLayout *DL) { ArrayType *ATy = cast(Load->getType()); - Value *NewStruct = UndefValue::get(ATy); + Value *NewArray = UndefValue::get(ATy); bool NeedsAnotherPass = false; - // Create a separate load instruction for each struct field. + // Create a separate load instruction for each array field. for (unsigned Index = 0; Index < ATy->getNumElements(); ++Index) { SmallVector Indexes; Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, 0))); @@ -303,20 +305,95 @@ static bool SplitUpArrayLoad(LoadInst *Load, const DataLayout *DL) { NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(NewLoad); ProcessArrayLoadOrStoreAttrs(NewLoad, Load, ATy, Index, DL); - // Reconstruct the struct value. + // Reconstruct the array value. SmallVector EVIndexes; EVIndexes.push_back(Index); - NewStruct = - CopyDebug(InsertValueInst::Create(NewStruct, NewLoad, EVIndexes, + NewArray = + CopyDebug(InsertValueInst::Create(NewArray, NewLoad, EVIndexes, Load->getName() + ".insert", Load), Load); } - Load->replaceAllUsesWith(NewStruct); + Load->replaceAllUsesWith(NewArray); Load->eraseFromParent(); return NeedsAnotherPass; } +static bool SplitUpArraySelect(SelectInst *Select) { + ArrayType *ATy = cast(Select->getType()); + Value *NewArray = UndefValue::get(ATy); + + bool NeedsAnotherPass = false; + // Create a separate select instruction for each array field. + for (unsigned Index = 0; Index < ATy->getNumElements(); ++Index) { + SmallVector EVIndexes; + EVIndexes.push_back(Index); + Value *TrueValue = ExtractValueInst::Create(Select->getTrueValue(), + EVIndexes, "", Select); + Value *FalseValue = ExtractValueInst::Create(Select->getFalseValue(), + EVIndexes, "", Select); + SelectInst *NewSelect = SelectInst::Create(Select->getCondition(), + TrueValue, FalseValue, + Select->getName(), + Select); + NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(NewSelect); + + // Reconstruct the struct value. + SmallVector IVIndexes; + IVIndexes.push_back(Index); + NewArray = + CopyDebug(InsertValueInst::Create(NewArray, NewSelect, IVIndexes, + Select->getName() + ".insert", Select), + Select); + } + Select->replaceAllUsesWith(NewArray); + Select->eraseFromParent(); + + return NeedsAnotherPass; +} + +static bool SplitUpArrayPHINode(PHINode *Phi) { + ArrayType *ATy = cast(Phi->getType()); + + Value *NewArray = UndefValue::get(ATy); + Instruction *NewArrayInsertPt = &*Phi->getParent()->getFirstInsertionPt(); + + bool NeedsAnotherPass = false; + + // Create a separate PHINode for each array field. + for (unsigned Index = 0; Index < ATy->getNumElements(); ++Index) { + SmallVector EVIndexes; + EVIndexes.push_back(Index); + + Type *ElemTy = ATy->getElementType(); + NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(ElemTy); + + PHINode *NewPhi = PHINode::Create(ElemTy, Phi->getNumIncomingValues(), + Phi->getName() + ".index", Phi); + CopyDebug(NewPhi, Phi); + for (unsigned PhiIndex = 0; PhiIndex < Phi->getNumIncomingValues(); + ++PhiIndex) { + BasicBlock *IncomingBB = Phi->getIncomingBlock(PhiIndex); + Value *EV = CopyDebug( + ExtractValueInst::Create(Phi->getIncomingValue(PhiIndex), EVIndexes, + Phi->getName() + ".extract", + IncomingBB->getTerminator()), + Phi); + NewPhi->addIncoming(EV, IncomingBB); + } + + // Reconstruct the original array value. + NewArray = CopyDebug(InsertValueInst::Create(NewArray, NewPhi, EVIndexes, + Phi->getName() + ".insert", + NewArrayInsertPt), + Phi); + } + Phi->replaceAllUsesWith(NewArray); + Phi->eraseFromParent(); + + return NeedsAnotherPass; +} + static bool ExpandExtractValue(ExtractValueInst *EV, SmallVectorImpl *ToErase) { // Search for the insertvalue instruction that inserts the struct field @@ -541,11 +618,17 @@ bool ExpandStructRegs::runOnFunction(Function &Func) { if (Phi->getType()->isStructTy()) { NeedsAnotherPass |= SplitUpPHINode(Phi); Changed = true; + }else if (Phi->getType()->isArrayTy()) { + NeedsAnotherPass |= SplitUpArrayPHINode(Phi); + Changed = true; } } else if (SelectInst *Select = dyn_cast(Inst)) { if (Select->getType()->isStructTy()) { NeedsAnotherPass |= SplitUpSelect(Select); Changed = true; + } else if (Select->getType()->isArrayTy()) { + NeedsAnotherPass |= SplitUpArraySelect(Select); + Changed = true; } } }