Esempio n. 1
0
Constant *Kleerer::get_assert_fail()
{
  Type *constCharPtrTy = TypeBuilder<const char *, false>::get(C);
  AttrListPtr attrs = attrs.addAttr(~0, Attribute::NoReturn);
  return M.getOrInsertFunction("__assert_fail", attrs, Type::getVoidTy(C),
                               constCharPtrTy, constCharPtrTy, uintType,
                               constCharPtrTy, NULL);
}
Esempio n. 2
0
void ValueEnumerator::EnumerateAttributes(const AttrListPtr &PAL) {
    if (PAL.isEmpty()) return;  // null is always 0.
    // Do a lookup.
    unsigned &Entry = AttributeMap[PAL.getRawPointer()];
    if (Entry == 0) {
        // Never saw this before, add it.
        Attributes.push_back(PAL);
        Entry = Attributes.size();
    }
}
Esempio n. 3
0
void Function::removeAttribute(unsigned i, Attributes attr) {
  AttrListPtr PAL = getAttributes();
  PAL = PAL.removeAttr(i, attr);
  setAttributes(PAL);
}
Esempio n. 4
0
//
// Method: runOnModule()
//
// Description:
//  Entry point for this LLVM pass.
//  Clone functions that take GEPs as arguments
//
// 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 GEPExprArgs::runOnModule(Module& M) {
  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;) {
          CallInst *CI = dyn_cast<CallInst>(I++);
          if(!CI)
            continue;

          if(CI->hasByValArgument())
            continue;
          // if the GEP calls a function, that is externally defined,
          // or might be changed, ignore this call site.
          Function *F = CI->getCalledFunction();

          if (!F || (F->isDeclaration() || F->mayBeOverridden())) 
            continue;
          if(F->hasStructRetAttr())
            continue;
          if(F->isVarArg())
            continue;

          // find the argument we must replace
          Function::arg_iterator ai = F->arg_begin(), ae = F->arg_end();
          unsigned argNum = 1;
          for(; argNum < CI->getNumOperands();argNum++, ++ai) {
            if(ai->use_empty())
              continue;
            if (isa<GEPOperator>(CI->getOperand(argNum)))
              break;
          }

          // if no argument was a GEP operator to be changed 
          if(ai == ae)
            continue;

          GEPOperator *GEP = dyn_cast<GEPOperator>(CI->getOperand(argNum));
          if(!GEP->hasAllConstantIndices())
            continue;

          // Construct the new Type
          // Appends the struct Type at the beginning
          std::vector<Type*>TP;
          TP.push_back(GEP->getPointerOperand()->getType());
          for(unsigned c = 1; c < CI->getNumOperands();c++) {
            TP.push_back(CI->getOperand(c)->getType());
          }

          //return type is same as that of original instruction
          FunctionType *NewFTy = FunctionType::get(CI->getType(), TP, false);
          Function *NewF;
          numSimplified++;
          if(numSimplified > 800) 
            return true;

          NewF = Function::Create(NewFTy,
                                  GlobalValue::InternalLinkage,
                                  F->getName().str() + ".TEST",
                                  &M);

          Function::arg_iterator NI = NewF->arg_begin();
          NI->setName("GEParg");
          ++NI;

          ValueToValueMapTy ValueMap;

          for (Function::arg_iterator II = F->arg_begin(); NI != NewF->arg_end(); ++II, ++NI) {
            ValueMap[II] = NI;
            NI->setName(II->getName());
            NI->addAttr(F->getAttributes().getParamAttributes(II->getArgNo() + 1));
          }
          NewF->setAttributes(NewF->getAttributes().addAttr(
              0, F->getAttributes().getRetAttributes()));
          // Perform the cloning.
          SmallVector<ReturnInst*,100> Returns;
          CloneFunctionInto(NewF, F, ValueMap, false, Returns);
          std::vector<Value*> fargs;
          for(Function::arg_iterator ai = NewF->arg_begin(), 
              ae= NewF->arg_end(); ai != ae; ++ai) {
            fargs.push_back(ai);
          }

          NewF->setAttributes(NewF->getAttributes().addAttr(
              ~0, F->getAttributes().getFnAttributes()));
          //Get the point to insert the GEP instr.
          SmallVector<Value*, 8> Ops(CI->op_begin()+1, CI->op_end());
          Instruction *InsertPoint;
          for (BasicBlock::iterator insrt = NewF->front().begin(); 
               isa<AllocaInst>(InsertPoint = insrt); ++insrt) {;}

          NI = NewF->arg_begin();
          SmallVector<Value*, 8> Indices;
          Indices.append(GEP->op_begin()+1, GEP->op_end());
          GetElementPtrInst *GEP_new = GetElementPtrInst::Create(cast<Value>(NI),
                                                                 Indices, 
                                                                 "", InsertPoint);
          fargs.at(argNum)->replaceAllUsesWith(GEP_new);
          unsigned j = argNum + 1;
          for(; j < CI->getNumOperands();j++) {
            if(CI->getOperand(j) == GEP)
              fargs.at(j)->replaceAllUsesWith(GEP_new);
          }

          SmallVector<AttributeWithIndex, 8> AttributesVec;

          // Get the initial attributes of the call
          AttrListPtr CallPAL = CI->getAttributes();
          Attributes RAttrs = CallPAL.getRetAttributes();
          Attributes FnAttrs = CallPAL.getFnAttributes();
          if (RAttrs)
            AttributesVec.push_back(AttributeWithIndex::get(0, RAttrs));

          SmallVector<Value*, 8> Args;
          Args.push_back(GEP->getPointerOperand());
          for(unsigned j =1;j<CI->getNumOperands();j++) {
            Args.push_back(CI->getOperand(j));
            // position in the AttributesVec
            if (Attributes Attrs = CallPAL.getParamAttributes(j))
              AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs));
          }
          // Create the new attributes vec.
          if (FnAttrs != Attribute::None)
            AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs));

          AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(),
                                                    AttributesVec.end());

          CallInst *CallI = CallInst::Create(NewF,Args,"", CI);
          CallI->setCallingConv(CI->getCallingConv());
          CallI->setAttributes(NewCallPAL);
          CI->replaceAllUsesWith(CallI);
          CI->eraseFromParent();
          changed = true;
        }
      }
    }
  } while(changed);
  return true;
}
/// DeleteDeadVarargs - If this is an function that takes a ... list, and if
/// llvm.vastart is never called, the varargs list is dead for the function.
bool DAE::DeleteDeadVarargs(Function &Fn) {
  assert(Fn.getFunctionType()->isVarArg() && "Function isn't varargs!");
  if (Fn.isDeclaration() || !Fn.hasLocalLinkage()) return false;

  // Ensure that the function is only directly called.
  if (Fn.hasAddressTaken())
    return false;

  // Okay, we know we can transform this function if safe.  Scan its body
  // looking for calls to llvm.vastart.
  for (Function::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) {
    for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
      if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
        if (II->getIntrinsicID() == Intrinsic::vastart)
          return false;
      }
    }
  }

  // If we get here, there are no calls to llvm.vastart in the function body,
  // remove the "..." and adjust all the calls.

  // Start by computing a new prototype for the function, which is the same as
  // the old function, but doesn't have isVarArg set.
  const FunctionType *FTy = Fn.getFunctionType();
  
  std::vector<const Type*> Params(FTy->param_begin(), FTy->param_end());
  FunctionType *NFTy = FunctionType::get(FTy->getReturnType(),
                                                Params, false);
  unsigned NumArgs = Params.size();

  // Create the new function body and insert it into the module...
  Function *NF = Function::Create(NFTy, Fn.getLinkage());
  NF->copyAttributesFrom(&Fn);
  Fn.getParent()->getFunctionList().insert(&Fn, NF);
  NF->takeName(&Fn);

  // Loop over all of the callers of the function, transforming the call sites
  // to pass in a smaller number of arguments into the new function.
  //
  std::vector<Value*> Args;
  while (!Fn.use_empty()) {
    CallSite CS = CallSite::get(Fn.use_back());
    Instruction *Call = CS.getInstruction();

    // Pass all the same arguments.
    Args.assign(CS.arg_begin(), CS.arg_begin()+NumArgs);

    // Drop any attributes that were on the vararg arguments.
    AttrListPtr PAL = CS.getAttributes();
    if (!PAL.isEmpty() && PAL.getSlot(PAL.getNumSlots() - 1).Index > NumArgs) {
      SmallVector<AttributeWithIndex, 8> AttributesVec;
      for (unsigned i = 0; PAL.getSlot(i).Index <= NumArgs; ++i)
        AttributesVec.push_back(PAL.getSlot(i));
      if (Attributes FnAttrs = PAL.getFnAttributes()) 
        AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs));
      PAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end());
    }

    Instruction *New;
    if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
      New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(),
                               Args.begin(), Args.end(), "", Call);
      cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
      cast<InvokeInst>(New)->setAttributes(PAL);
    } else {
      New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call);
      cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
      cast<CallInst>(New)->setAttributes(PAL);
      if (cast<CallInst>(Call)->isTailCall())
        cast<CallInst>(New)->setTailCall();
    }
    if (MDNode *N = Call->getDbgMetadata())
      New->setDbgMetadata(N);

    Args.clear();

    if (!Call->use_empty())
      Call->replaceAllUsesWith(New);

    New->takeName(Call);

    // Finally, remove the old call from the program, reducing the use-count of
    // F.
    Call->eraseFromParent();
  }

  // Since we have now created the new function, splice the body of the old
  // function right into the new function, leaving the old rotting hulk of the
  // function empty.
  NF->getBasicBlockList().splice(NF->begin(), Fn.getBasicBlockList());

  // Loop over the argument list, transfering uses of the old arguments over to
  // the new arguments, also transfering over the names as well.  While we're at
  // it, remove the dead arguments from the DeadArguments list.
  //
  for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(),
       I2 = NF->arg_begin(); I != E; ++I, ++I2) {
    // Move the name and users over to the new version.
    I->replaceAllUsesWith(I2);
    I2->takeName(I);
  }

  // Finally, nuke the old function.
  Fn.eraseFromParent();
  return true;
}
int compile(list<string> args, list<string> kgen_args,
            string merge, list<string> merge_args,
            string input, string output, int arch,
            string host_compiler, string fileprefix)
{
    //
    // The LLVM compiler to emit IR.
    //
    const char* llvm_compiler = "kernelgen-gfortran";

    //
    // Interpret kernelgen compile options.
    //
    for (list<string>::iterator iarg = kgen_args.begin(),
            iearg = kgen_args.end(); iarg != iearg; iarg++)
    {
        const char* arg = (*iarg).c_str();
        if (!strncmp(arg, "-Wk,--llvm-compiler=", 20))
            llvm_compiler = arg + 20;
    }

    //
    // Generate temporary output file.
    // Check if output file is specified in the command line.
    // Replace or add output to the temporary file.
    //
    cfiledesc tmp_output = cfiledesc::mktemp(fileprefix);
    bool output_specified = false;
    for (list<string>::iterator iarg = args.begin(),
            iearg = args.end(); iarg != iearg; iarg++)
    {
        const char* arg = (*iarg).c_str();
        if (!strcmp(arg, "-o"))
        {
            iarg++;
            *iarg = tmp_output.getFilename();
            output_specified = true;
            break;
        }
    }
    if (!output_specified)
    {
        args.push_back("-o");
        args.push_back(tmp_output.getFilename());
    }

    //
    // 1) Compile source code using regular host compiler.
    //
    {
        if (verbose)
        {
            cout << host_compiler;
            for (list<string>::iterator iarg = args.begin(),
                    iearg = args.end(); iarg != iearg; iarg++)
                cout << " " << *iarg;
            cout << endl;
        }
        int status = execute(host_compiler, args, "", NULL, NULL);
        if (status) return status;
    }

    //
    // 2) Emit LLVM IR.
    //
    string out = "";
    {
        list<string> emit_ir_args;
        for (list<string>::iterator iarg = args.begin(),
                iearg = args.end(); iarg != iearg; iarg++)
        {
            const char* arg = (*iarg).c_str();
            if (!strcmp(arg, "-c") || !strcmp(arg, "-o"))
            {
                iarg++;
                continue;
            }
            if (!strcmp(arg, "-g"))
            {
                continue;
            }
            emit_ir_args.push_back(*iarg);
        }
        emit_ir_args.push_back("-fplugin=/opt/kernelgen/lib/dragonegg.so");
        emit_ir_args.push_back("-fplugin-arg-dragonegg-emit-ir");
        emit_ir_args.push_back("-S");
        emit_ir_args.push_back(input);
        emit_ir_args.push_back("-o");
        emit_ir_args.push_back("-");
        if (verbose)
        {
            cout << llvm_compiler;
            for (list<string>::iterator iarg = emit_ir_args.begin(),
                    iearg = emit_ir_args.end(); iarg != iearg; iarg++)
                cout << " " << *iarg;
            cout << endl;
        }
        int status = execute(llvm_compiler, emit_ir_args, "", &out, NULL);
        if (status) return status;
    }

    //
    // 3) Record existing module functions.
    //
    LLVMContext &context = getGlobalContext();
    SMDiagnostic diag;
    MemoryBuffer* buffer1 = MemoryBuffer::getMemBuffer(out);
    auto_ptr<Module> m1;
    m1.reset(ParseIR(buffer1, diag, context));

    //m1.get()->dump();

    //
    // 4) Inline calls and extract loops into new functions.
    //
    MemoryBuffer* buffer2 = MemoryBuffer::getMemBuffer(out);
    auto_ptr<Module> m2;
    m2.reset(ParseIR(buffer2, diag, context));
    {
        PassManager manager;
        manager.add(createInstructionCombiningPass());
        manager.run(*m2.get());
    }
    std::vector<CallInst *> LoopFuctionCalls;
    {
        PassManager manager;
        manager.add(createBranchedLoopExtractorPass(LoopFuctionCalls));
        manager.run(*m2.get());
    }

    //m2.get()->dump();

    //
    // 5) Replace call to loop functions with call to launcher.
    // Append "always inline" attribute to all other functions.
    //
    Type* int32Ty = Type::getInt32Ty(context);
    Function* launch = Function::Create(
                           TypeBuilder<types::i<32>(types::i<8>*, types::i<64>, types::i<32>*), true>::get(context),
                           GlobalValue::ExternalLinkage, "kernelgen_launch", m2.get());
    for (Module::iterator f1 = m2.get()->begin(), fe1 = m2.get()->end(); f1 != fe1; f1++)
    {
        Function* func = f1;
        if (func->isDeclaration()) continue;

        // Search for the current function in original module
        // functions list.
        // If function is not in list of original module, then
        // it is generated by the loop extractor.
        // Append "always inline" attribute to all other functions.
        if (m1.get()->getFunction(func->getName()))
        {
            const AttrListPtr attr = func->getAttributes();
            const AttrListPtr attr_new = attr.addAttr(~0U, Attribute::AlwaysInline);
            func->setAttributes(attr_new);
            continue;
        }

        // Each such function must be extracted to the
        // standalone module and packed into resulting
        // object file data section.
        if (verbose)
            cout << "Preparing loop function " << func->getName().data() <<
                 " ..." << endl;

        // Reset to default visibility.
        func->setVisibility(GlobalValue::DefaultVisibility);

        // Reset to default linkage.
        func->setLinkage(GlobalValue::ExternalLinkage);

        // Replace call to this function in module with call to launcher.
        bool found = false;
        for (Module::iterator f2 = m2->begin(), fe2 = m2->end(); (f2 != fe2) && !found; f2++)
            for (Function::iterator bb = f2->begin(); (bb != f2->end()) && !found; bb++)
                for (BasicBlock::iterator i = bb->begin(); i != bb->end(); i++)
                {
                    // Check if instruction in focus is a call.
                    CallInst* call = dyn_cast<CallInst>(cast<Value>(i));
                    if (!call) continue;

                    // Check if function is called (needs -instcombine pass).
                    Function* callee = call->getCalledFunction();
                    if (!callee) continue;
                    if (callee->isDeclaration()) continue;
                    if (callee->getName() != func->getName()) continue;

                    // Create a constant array holding original called
                    // function name.
                    Constant* name = ConstantArray::get(
                                         context, callee->getName(), true);

                    // Create and initialize the memory buffer for name.
                    ArrayType* nameTy = cast<ArrayType>(name->getType());
                    AllocaInst* nameAlloc = new AllocaInst(nameTy, "", call);
                    StoreInst* nameInit = new StoreInst(name, nameAlloc, "", call);
                    Value* Idx[2];
                    Idx[0] = Constant::getNullValue(Type::getInt32Ty(context));
                    Idx[1] = ConstantInt::get(Type::getInt32Ty(context), 0);
                    GetElementPtrInst* namePtr = GetElementPtrInst::Create(nameAlloc, Idx, "", call);

                    // Add pointer to the original function string name.
                    SmallVector<Value*, 16> call_args;
                    call_args.push_back(namePtr);

                    // Add size of the aggregated arguments structure.
                    {
                        BitCastInst* BC = new BitCastInst(
                            call->getArgOperand(0), Type::getInt64PtrTy(context),
                            "", call);

                        LoadInst* LI = new LoadInst(BC, "", call);
                        call_args.push_back(LI);
                    }

                    // Add original aggregated structure argument.
                    call_args.push_back(call->getArgOperand(0));

                    // Create new function call with new call arguments
                    // and copy old call properties.
                    CallInst* newcall = CallInst::Create(launch, call_args, "", call);
                    //newcall->takeName(call);
                    newcall->setCallingConv(call->getCallingConv());
                    newcall->setAttributes(call->getAttributes());
                    newcall->setDebugLoc(call->getDebugLoc());

                    // Replace old call with new one.
                    call->replaceAllUsesWith(newcall);
                    call->eraseFromParent();

                    found = true;
                    break;
                }
    }

    //m2.get()->dump();

    //
    // 6) Apply optimization passes to the resulting common
    // module.
    //
    {
        PassManager manager;
        manager.add(createLowerSetJmpPass());
        PassManagerBuilder builder;
        builder.Inliner = createFunctionInliningPass();
        builder.OptLevel = 3;
        builder.DisableSimplifyLibCalls = true;
        builder.populateModulePassManager(manager);
        manager.run(*m2.get());
    }

    //m2.get()->dump();

    //
    // 7) Embed the resulting module into object file.
    //
    {
        string ir_string;
        raw_string_ostream ir(ir_string);
        ir << (*m2.get());
        celf e(tmp_output.getFilename(), output);
        e.getSection(".data")->addSymbol(
            "__kernelgen_" + string(input),
            ir_string.c_str(), ir_string.size() + 1);
    }

    return 0;
}
Esempio n. 7
0
void LLVMRemoveFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA) {
  Function *Func = unwrap<Function>(Fn);
  const AttrListPtr PAL = Func->getAttributes();
  const AttrListPtr PALnew = PAL.removeAttr(0, PA);
  Func->setAttributes(PALnew);
}