Ejemplo n.º 1
0
    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);
      }
    }
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
    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";
    }
Ejemplo n.º 4
0
 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;
  }
Ejemplo n.º 6
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;
  }
Ejemplo n.º 7
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;
}