void GraphBuilder::visitExtractValueInst(ExtractValueInst& I) { DSNodeHandle Ptr = getValueDest(I.getOperand(0)); // Make that the node is read from... Ptr.getNode()->setReadMarker(); unsigned Offset = 0; Type* STy = I.getAggregateOperand()->getType(); llvm::ExtractValueInst::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 typerecord exists... Ptr.getNode()->mergeTypeInfo(I.getType(), Offset); if (isa<PointerType>(I.getType())) setDestTo(I, getLink(Ptr)); }
bool ExtractValueInstrumenter::CheckAndInstrument(Instruction* inst) { ExtractValueInst* evInst = dyn_cast<ExtractValueInst>(inst); if (evInst == NULL) { return false; } safe_assert(parent_ != NULL); count_++; InstrPtrVector instrs; Constant* iidC = IID_CONSTANT(evInst); Constant* inxC = computeIndex(evInst); Value* aggOp = evInst->getAggregateOperand(); Constant* aggOpInxC = computeIndex(aggOp); KVALUE_STRUCTVALUE(aggOp, instrs); for (ExtractValueInst::idx_iterator idx = evInst->idx_begin(); idx != evInst->idx_end(); idx++) { Constant* idxOp = INT32_CONSTANT(*idx, UNSIGNED); Instruction* call = CALL_INT("llvm_push_getelementptr_inx2", idxOp); instrs.push_back(call); } Instruction* call = CALL_IID_INT_INT("llvm_extractvalue", iidC, inxC, aggOpInxC); instrs.push_back(call); InsertAllBefore(instrs, evInst); return true; }
// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. Search for insert/extractvalue 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 SimplifyEV::runOnModule(Module& M) { // Repeat till no change bool changed; do { changed = false; 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;) { ExtractValueInst *EV = dyn_cast<ExtractValueInst>(I++); if(!EV) continue; Value *Agg = EV->getAggregateOperand(); if (!EV->hasIndices()) { EV->replaceAllUsesWith(Agg); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); DEBUG(EV->dump()); EV->eraseFromParent(); numErased++; changed = true; continue; } if (Constant *C = dyn_cast<Constant>(Agg)) { if (isa<UndefValue>(C)) { EV->replaceAllUsesWith(UndefValue::get(EV->getType())); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); DEBUG(EV->dump()); EV->eraseFromParent(); numErased++; changed = true; continue; } if (isa<ConstantAggregateZero>(C)) { EV->replaceAllUsesWith(Constant::getNullValue(EV->getType())); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); DEBUG(EV->dump()); EV->eraseFromParent(); numErased++; changed = true; continue; } if (isa<ConstantArray>(C) || isa<ConstantStruct>(C)) { // Extract the element indexed by the first index out of the constant Value *V = C->getOperand(*EV->idx_begin()); if (EV->getNumIndices() > 1) { // Extract the remaining indices out of the constant indexed by the // first index ExtractValueInst *EV_new = ExtractValueInst::Create(V, EV->getIndices().slice(1), "", EV); EV->replaceAllUsesWith(EV_new); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); DEBUG(EV->dump()); EV->eraseFromParent(); numErased++; changed = true; continue; } else { EV->replaceAllUsesWith(V); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); DEBUG(EV->dump()); EV->eraseFromParent(); numErased++; changed = true; continue; } } continue; } if (LoadInst * LI = dyn_cast<LoadInst>(Agg)) { // if the Agg value came from a load instruction // replace the extract value intruction with // a gep and a load. SmallVector<Value*, 8> Indices; Type *Int32Ty = Type::getInt32Ty(M.getContext()); Indices.push_back(Constant::getNullValue(Int32Ty)); for (ExtractValueInst::idx_iterator I = EV->idx_begin(), E = EV->idx_end(); I != E; ++I) { Indices.push_back(ConstantInt::get(Int32Ty, *I)); } GetElementPtrInst *GEP = GetElementPtrInst::CreateInBounds(LI->getOperand(0), Indices, LI->getName(), LI) ; LoadInst *LINew = new LoadInst(GEP, "", LI); EV->replaceAllUsesWith(LINew); EV->eraseFromParent(); changed = true; numErased++; continue; } if (InsertValueInst *IV = dyn_cast<InsertValueInst>(Agg)) { bool done = false; // We're extracting from an insertvalue instruction, compare the indices const unsigned *exti, *exte, *insi, *inse; for (exti = EV->idx_begin(), insi = IV->idx_begin(), exte = EV->idx_end(), inse = IV->idx_end(); exti != exte && insi != inse; ++exti, ++insi) { if (*insi != *exti) { // The insert and extract both reference distinctly different elements. // This means the extract is not influenced by the insert, and we can // replace the aggregate operand of the extract with the aggregate // operand of the insert. i.e., replace // %I = insertvalue { i32, { i32 } } %A, { i32 } { i32 42 }, 1 // %E = extractvalue { i32, { i32 } } %I, 0 // with // %E = extractvalue { i32, { i32 } } %A, 0 ExtractValueInst *EV_new = ExtractValueInst::Create(IV->getAggregateOperand(), EV->getIndices(), "", EV); EV->replaceAllUsesWith(EV_new); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); DEBUG(EV->dump()); EV->eraseFromParent(); numErased++; done = true; changed = true; break; } } if(done) continue; if (exti == exte && insi == inse) { // Both iterators are at the end: Index lists are identical. Replace // %B = insertvalue { i32, { i32 } } %A, i32 42, 1, 0 // %C = extractvalue { i32, { i32 } } %B, 1, 0 // with "i32 42" EV->replaceAllUsesWith(IV->getInsertedValueOperand()); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); DEBUG(EV->dump()); EV->eraseFromParent(); numErased++; changed = true; continue; } if (exti == exte) { // The extract list is a prefix of the insert list. i.e. replace // %I = insertvalue { i32, { i32 } } %A, i32 42, 1, 0 // %E = extractvalue { i32, { i32 } } %I, 1 // with // %X = extractvalue { i32, { i32 } } %A, 1 // %E = insertvalue { i32 } %X, i32 42, 0 // by switching the order of the insert and extract (though the // insertvalue should be left in, since it may have other uses). Value *NewEV = ExtractValueInst::Create(IV->getAggregateOperand(), EV->getIndices(), "", EV); Value *NewIV = InsertValueInst::Create(NewEV, IV->getInsertedValueOperand(), makeArrayRef(insi, inse), "", EV); EV->replaceAllUsesWith(NewIV); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); DEBUG(EV->dump()); EV->eraseFromParent(); numErased++; changed = true; continue; } if (insi == inse) { // The insert list is a prefix of the extract list // We can simply remove the common indices from the extract and make it // operate on the inserted value instead of the insertvalue result. // i.e., replace // %I = insertvalue { i32, { i32 } } %A, { i32 } { i32 42 }, 1 // %E = extractvalue { i32, { i32 } } %I, 1, 0 // with // %E extractvalue { i32 } { i32 42 }, 0 ExtractValueInst *EV_new = ExtractValueInst::Create(IV->getInsertedValueOperand(), makeArrayRef(exti, exte), "", EV); EV->replaceAllUsesWith(EV_new); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); DEBUG(EV->dump()); EV->eraseFromParent(); numErased++; changed = true; continue; } } } } } } while(changed); return (numErased > 0); }