// This is the recursive version of BuildSubAggregate. It takes a few different // arguments. Idxs is the index within the nested struct From that we are // looking at now (which is of type IndexedType). IdxSkip is the number of // indices from Idxs that should be left out when inserting into the resulting // struct. To is the result struct built so far, new insertvalue instructions // build on that. Value *BuildSubAggregate(Value *From, Value* To, const Type *IndexedType, SmallVector<unsigned, 10> &Idxs, unsigned IdxSkip, Instruction *InsertBefore) { const llvm::StructType *STy = llvm::dyn_cast<llvm::StructType>(IndexedType); if (STy) { // Save the original To argument so we can modify it Value *OrigTo = To; // General case, the type indexed by Idxs is a struct for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { // Process each struct element recursively Idxs.push_back(i); Value *PrevTo = To; To = BuildSubAggregate(From, To, STy->getElementType(i), Idxs, IdxSkip, InsertBefore); Idxs.pop_back(); if (!To) { // Couldn't find any inserted value for this index? Cleanup while (PrevTo != OrigTo) { InsertValueInst* Del = cast<InsertValueInst>(PrevTo); PrevTo = Del->getAggregateOperand(); Del->eraseFromParent(); } // Stop processing elements break; } } // If we succesfully found a value for each of our subaggregates if (To) return To; } // Base case, the type indexed by SourceIdxs is not a struct, or not all of // the struct's elements had a value that was inserted directly. In the latter // case, perhaps we can't determine each of the subelements individually, but // we might be able to find the complete struct somewhere. // Find the value that is at that particular spot Value *V = FindInsertedValue(From, Idxs.begin(), Idxs.end()); if (!V) return NULL; // Insert the value in the new (sub) aggregrate return llvm::InsertValueInst::Create(To, V, Idxs.begin() + IdxSkip, Idxs.end(), "tmp", InsertBefore); }
bool CallAnalyzer::visitInsertValue(InsertValueInst &I) { // Constant folding for insert value is trivial. Constant *AggC = dyn_cast<Constant>(I.getAggregateOperand()); if (!AggC) AggC = SimplifiedValues.lookup(I.getAggregateOperand()); Constant *InsertedC = dyn_cast<Constant>(I.getInsertedValueOperand()); if (!InsertedC) InsertedC = SimplifiedValues.lookup(I.getInsertedValueOperand()); if (AggC && InsertedC) { SimplifiedValues[&I] = ConstantExpr::getInsertValue(AggC, InsertedC, I.getIndices()); return true; } // SROA can look through these but give them a cost. return false; }
void GraphBuilder::visitInsertValueInst(InsertValueInst& I) { setDestTo(I, createNode()->setAllocaMarker()); Type *StoredTy = I.getInsertedValueOperand()->getType(); DSNodeHandle Dest = getValueDest(&I); Dest.mergeWith(getValueDest(I.getAggregateOperand())); // Mark that the node is written to... Dest.getNode()->setModifiedMarker(); unsigned Offset = 0; Type* STy = I.getAggregateOperand()->getType(); llvm::InsertValueInst::idx_iterator i = I.idx_begin(), e = I.idx_end(); for (; i != e; i++) { const StructLayout *SL = TD.getStructLayout(cast<StructType>(STy)); Offset += SL->getElementOffset(*i); STy = (cast<StructType>(STy))->getTypeAtIndex(*i); } // Ensure a type-record exists... Dest.getNode()->mergeTypeInfo(StoredTy, Offset); // Avoid adding edges from null, or processing non-"pointer" stores if (isa<PointerType>(StoredTy)) Dest.addEdgeTo(getValueDest(I.getInsertedValueOperand())); }
// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. Search for insertvalue instructions // that can be simplified. // // Inputs: // M - A reference to the LLVM module to transform. // // Outputs: // M - The transformed LLVM module. // // Return value: // true - The module was modified. // false - The module was not modified. // bool SimplifyIV::runOnModule(Module& M) { // Repeat till no change bool changed; do { changed = false; std::vector<StoreInst*> worklist; for (Module::iterator F = M.begin(); F != M.end(); ++F) { for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) { for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) { InsertValueInst *IV = dyn_cast<InsertValueInst>(I++); if(!IV) continue; // Find all insert value instructions. if(!IV->hasOneUse()) continue; // Check that its only use is a StoreInst StoreInst *SI = dyn_cast<StoreInst>(*(IV->use_begin())); if(!SI) continue; // Check that it is the stored value if(SI->getOperand(0) != IV) continue; changed = true; numErased++; do { // replace by a series of gep/stores SmallVector<Value*, 8> Indices; Type *Int32Ty = Type::getInt32Ty(M.getContext()); Indices.push_back(Constant::getNullValue(Int32Ty)); for (InsertValueInst::idx_iterator I = IV->idx_begin(), E = IV->idx_end(); I != E; ++I) { Indices.push_back(ConstantInt::get(Int32Ty, *I)); } GetElementPtrInst *GEP = GetElementPtrInst::CreateInBounds(SI->getOperand(1), Indices, SI->getName(), SI) ; new StoreInst(IV->getInsertedValueOperand(), GEP, SI); IV = dyn_cast<InsertValueInst>(IV->getAggregateOperand()); } while(IV); worklist.push_back(SI); } } } while(!worklist.empty()) { StoreInst *SI = worklist.back(); worklist.pop_back(); SI->eraseFromParent(); } } while(changed); return (numErased > 0); }
/// GetExceptionObject - Return the exception object from the value passed into /// the 'resume' instruction (typically an aggregate). Clean up any dead /// instructions, including the 'resume' instruction. Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) { Value *V = RI->getOperand(0); Value *ExnObj = 0; InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V); LoadInst *SelLoad = 0; InsertValueInst *ExcIVI = 0; bool EraseIVIs = false; if (SelIVI) { if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) { ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0)); if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) && ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) { ExnObj = ExcIVI->getOperand(1); SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1)); EraseIVIs = true; } } } if (!ExnObj) ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI); RI->eraseFromParent(); if (EraseIVIs) { if (SelIVI->getNumUses() == 0) SelIVI->eraseFromParent(); if (ExcIVI->getNumUses() == 0) ExcIVI->eraseFromParent(); if (SelLoad && SelLoad->getNumUses() == 0) SelLoad->eraseFromParent(); } return ExnObj; }