void codeInto<proto::ComponentInterfaceTransform, ComponentInterfaceTransform> ( const proto::ComponentInterfaceTransform& buf, ComponentInterfaceTransform& ci) { if (ci.interface == NULL) { ci.ownsIface = true; ci.interface = new ComponentInterface(); } assert (ci.interface != NULL); for (int i = 0; i < buf.calls_size(); i++) { const proto::CallRewrite& rw = buf.calls(i); const proto::CallInfo& info = rw.call(); StringRef name = info.name(); CallInfo res; codeInto<proto::CallInfo, CallInfo> (info, res); CallInfo* result = ci.interface->getOrCreateCall(name, res.args); result->count += info.count(); CallRewrite rewrite; codeInto<proto::CallRewrite, CallRewrite> (rw, rewrite); ci.rewrite(name, result, rewrite); } }
bool TransformComponentWithUse(Module& M, ComponentInterfaceTransform& T) { bool modified = false; for (ComponentInterfaceTransform::FMap::const_iterator i = T.rewrites.begin(), e = T.rewrites.end(); i != e; ++i) { errs() << "Looking for calls to " << i->first << "\n"; Function* f = M.getFunction(i->first); if (f == NULL) continue; for (Function::use_iterator ui = f->use_begin(), ue = f->use_end(); ui != ue; ++ui) { Use* use = &(*ui); User* user = ui->getUser(); if (isa<CallInst>(user) || isa<InvokeInst>(user)) { // The instruction is a call site CallSite cs(cast<Instruction>(user)); // If we are not the callee we should bail if( ! cs.isCallee(use)) { continue; } const CallRewrite* const rw = T.lookupRewrite(i->first, cs.arg_begin(), cs.arg_end()); if (rw == NULL) { continue; } #if DUMP BasicBlock* owner = cs.getInstruction()->getParent(); errs() << "Specializing (inter-module) call to '" << cs.getCalledFunction()->getName() << "' in function '" << (owner == NULL ? "??" : owner->getParent()->getName()) << "' on arguments ["; for (unsigned int i = 0, cnt = 0; i < cs.arg_size(); ++i) { if (!vector_in(rw->args, i)) { if (cnt++ != 0) errs() << ","; errs() << i << "=(" << *cs.getArgument(i) << ")"; } } errs() << "]\n"; #endif Instruction* newInst = applyRewriteToCall(M, rw, cs); llvm::ReplaceInstWithInst(cs.getInstruction(), newInst); modified = true; } } } return modified; }
RewriteComponentPass() : ModulePass(ID), transform() { errs() << "RewriteComponentPass()\n"; for (cl::list<std::string>::const_iterator b = RewriteComponentInput.begin(), e = RewriteComponentInput.end(); b != e; ++b) { errs() << "Reading file '" << *b << "'..."; if (transform.readTransformFromFile(*b)) { errs() << "success\n"; } else { errs() << "failed\n"; } } transform.dump(); errs() << "Done reading (" << transform.rewriteCount() << " rewrites)\n"; }
void codeInto<ComponentInterfaceTransform, proto::ComponentInterfaceTransform> ( const ComponentInterfaceTransform& ci, proto::ComponentInterfaceTransform& buf) { for (ComponentInterface::FunctionIterator fi = ci.interface->begin(), fe = ci.interface->end(); fi != fe; ++fi) { for (ComponentInterface::CallIterator c = ci.interface->call_begin(fi), e = ci.interface->call_end(fi); c != e; ++c) { const CallRewrite* rw = ci.lookupRewrite(fi->first(), *c); if (rw != NULL) { proto::CallRewrite* nrw = buf.add_calls(); codeInto<CallRewrite, proto::CallRewrite> (*rw, *nrw); nrw->mutable_call()->set_name(fi->first()); codeInto<CallInfo, proto::CallInfo> (**c, *nrw->mutable_call()); } } } }
/* * Reduce this module with respect to the given interface. * - The interface suggests some of the uses of the functions, * so here we can generate special versions of those functions. * Generate a ComponentInterfaceTransform for clients to rewrite their * code to use the new API */ bool SpecializeComponent(Module& M, ComponentInterfaceTransform& T, SpecializationPolicy &policy, std::list<Function*>& to_add) { int rewrite_count = 0; const ComponentInterface& I = T.getInterface(); // TODO: What needs to be done? // - Should try to handle strings & arrays for (ComponentInterface::FunctionIterator ff = I.begin(), fe = I.end(); ff != fe; ++ff) { StringRef name = ff->first(); Function* func = resolveFunction(M, name); if (func == NULL || func->isDeclaration()) { // We don't specialize declarations because we don't own them continue; } for (ComponentInterface::CallIterator cc = I.call_begin(name), ce = I.call_end(name); cc != ce; ++cc) { const CallInfo* const call = *cc; const unsigned arg_count = call->args.size(); if (func->isVarArg()) { // TODO: I don't know how to specialize variable argument functions yet continue; } if (arg_count != func->getArgumentList().size()) { // Not referring to this function? // NOTE: I can't assert this equality because of the way that approximations occur continue; } SmallBitVector slice(arg_count); bool shouldSpecialize = policy.specializeOn(func, call->args.begin(), call->args.end(), slice); if (!shouldSpecialize) continue; std::vector<Value*> args; std::vector<unsigned> argPerm; args.reserve(arg_count); argPerm.reserve(slice.count()); for (unsigned i = 0; i < arg_count; i++) { if (slice.test(i)) { Type * paramType = func->getFunctionType()->getParamType(i); Value *concreteArg = call->args[i].concretize(M, paramType); args.push_back(concreteArg); assert(concreteArg->getType() == paramType && "Specializing function with concrete argument of wrong type!"); } else { args.push_back(NULL); argPerm.push_back(i); } } Function* nfunc = specializeFunction(func, args); nfunc->setLinkage(GlobalValue::ExternalLinkage); FunctionHandle rewriteTo = nfunc->getName(); T.rewrite(name, call, rewriteTo, argPerm); to_add.push_back(nfunc); rewrite_count++; } } if (rewrite_count > 0) { errs() << rewrite_count << " pending rewrites\n"; } return rewrite_count > 0; }
/* * Reduce this module with respect to the given interface. * - The interface suggests some of the uses of the functions, * so here we can generate special versions of those functions. * Generate a ComponentInterfaceTransform for clients to rewrite their * code to use the new API */ bool SpecializeComponent(Module& M, ComponentInterfaceTransform& T, SpecializationPolicy &policy, std::list<Function*>& to_add) { errs() << "SpecializeComponent()\n"; int rewrite_count = 0; const ComponentInterface& I = T.getInterface(); // TODO: What needs to be done? // - Should try to handle strings & arrays // Iterate through all functions in the interface of T for (ComponentInterface::FunctionIterator ff = I.begin(), fe = I.end(); ff != fe; ++ff) { StringRef name = ff->first(); Function* func = resolveFunction(M, name); if (func == NULL || func->isDeclaration()) { // We don't specialize declarations because we don't own them continue; } // Now iterate through all calls to func in the interface of T for (ComponentInterface::CallIterator cc = I.call_begin(name), ce = I.call_end(name); cc != ce; ++cc) { const CallInfo* const call = *cc; const unsigned arg_count = call->args.size(); if (func->isVarArg()) { // TODO: I don't know how to specialize variable argument functions yet continue; } if (arg_count != func->getArgumentList().size()) { // Not referring to this function? // NOTE: I can't assert this equality because of the way that approximations occur continue; } /* should we specialize? if yes then each bit in slice will indicate whether the argument is a specializable constant */ SmallBitVector slice(arg_count); bool shouldSpecialize = policy.specializeOn(func, call->args.begin(), call->args.end(), slice); if (!shouldSpecialize) continue; std::vector<Value*> args; std::vector<unsigned> argPerm; args.reserve(arg_count); argPerm.reserve(slice.count()); for (unsigned i = 0; i < arg_count; i++) { if (slice.test(i)) { Type * paramType = func->getFunctionType()->getParamType(i); Value *concreteArg = call->args[i].concretize(M, paramType); args.push_back(concreteArg); assert(concreteArg->getType() == paramType && "Specializing function with concrete argument of wrong type!"); } else { args.push_back(NULL); argPerm.push_back(i); } } /* args is a list of pointers to values -- if the pointer is NULL then that argument is not specialized -- if the pointer is not NULL then the argument will be/has been specialized to that value argsPerm is a list on integers; the indices of the non-special arguments args[i] = NULL iff i is in argsPerm for i < arg_count. */ Function* nfunc = specializeFunction(func, args); nfunc->setLinkage(GlobalValue::ExternalLinkage); FunctionHandle rewriteTo = nfunc->getName(); T.rewrite(name, call, rewriteTo, argPerm); to_add.push_back(nfunc); errs() << "Specialized " << name << " to " << rewriteTo << "\n"; #if 0 for (unsigned i = 0; i < arg_count; i++) { errs() << "i = " << i << ": slice[i] = " << slice[i] << " args[i] = " << args.at(i) << "\n"; } errs() << " argPerm = ["; for (unsigned i = 0; i < argPerm.size(); i++) { errs() << argPerm.at(i) << " "; } errs() << "]\n"; #endif rewrite_count++; } } if (rewrite_count > 0) { errs() << rewrite_count << " pending rewrites\n"; } return rewrite_count > 0; }
/* * Rewrite the given module according to the ComponentInterfaceTransformer. */ bool TransformComponentWithoutUse(Module& M, ComponentInterfaceTransform& T) { assert(T.interface != NULL); bool modified = false; for (Module::iterator f = M.begin(), e = M.end(); f != e; ++f) { for (Function::iterator bb = f->begin(), bbe = f->end(); bb != bbe; ++bb) { for (BasicBlock::iterator I = bb->begin(), E = bb->end(); I != E; ++I) { // TODO: Handle the operands CallSite call; if (CallInst* ci = dyn_cast<CallInst>(&*I)) { if (ci->isInlineAsm()) continue; call = CallSite(ci); } else if (InvokeInst* ci = dyn_cast<InvokeInst>(&*I)) { call = CallSite(ci); } else { // TODO: We need to find all references, including ones stored in variables // we'll be conservative and say that if it is stored in a variable then // we can't optimize it at all continue; } Function* target = call.getCalledFunction(); if (target == NULL || !target->isDeclaration()) { continue; } //iam const CallRewrite* const rw = T.lookupRewrite(target->getNameStr(), call.arg_begin(), call.arg_end()); const CallRewrite* const rw = T.lookupRewrite(target->getName().str(), call.arg_begin(), call.arg_end()); if (rw == NULL) { // There is no rewrite for this function continue; } // Get/Create the function Function* newTarget = M.getFunction(rw->function); if (newTarget == NULL) { // There isn't a function, we need to construct it FunctionType* newType = target->getFunctionType(); std::vector<Type*> argTypes; for (std::vector<unsigned>::const_iterator i = rw->args.begin(), e = rw->args.end(); i != e; ++i) argTypes.push_back(newType->getParamType(*i)); ArrayRef<Type*> params(argTypes); newType = FunctionType::get(target->getReturnType(), params, target->isVarArg()); newTarget = dyn_cast<Function> (M.getOrInsertFunction(rw->function, newType)); } assert(newTarget != NULL); Instruction* newInst = specializeCallSite(I, newTarget, rw->args); llvm::ReplaceInstWithInst(bb->getInstList(), I, newInst); modified = true; } } } return modified; }