bool AMDGPUPromoteAlloca::runOnFunction(Function &F) {

  const FunctionType *FTy = F.getFunctionType();

  LocalMemAvailable = ST.getLocalMemorySize();


  // If the function has any arguments in the local address space, then it's
  // possible these arguments require the entire local memory space, so
  // we cannot use local memory in the pass.
  for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) {
    const Type *ParamTy = FTy->getParamType(i);
    if (ParamTy->isPointerTy() &&
        ParamTy->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
      LocalMemAvailable = 0;
      DEBUG(dbgs() << "Function has local memory argument.  Promoting to "
                      "local memory disabled.\n");
      break;
    }
  }

  if (LocalMemAvailable > 0) {
    // Check how much local memory is being used by global objects
    for (Module::global_iterator I = Mod->global_begin(),
                                 E = Mod->global_end(); I != E; ++I) {
      GlobalVariable *GV = I;
      PointerType *GVTy = GV->getType();
      if (GVTy->getAddressSpace() != AMDGPUAS::LOCAL_ADDRESS)
        continue;
      for (Value::use_iterator U = GV->use_begin(),
                               UE = GV->use_end(); U != UE; ++U) {
        Instruction *Use = dyn_cast<Instruction>(*U);
        if (!Use)
          continue;
        if (Use->getParent()->getParent() == &F)
          LocalMemAvailable -=
              Mod->getDataLayout()->getTypeAllocSize(GVTy->getElementType());
      }
    }
  }

  LocalMemAvailable = std::max(0, LocalMemAvailable);
  DEBUG(dbgs() << LocalMemAvailable << "bytes free in local memory.\n");

  visit(F);

  return false;
}
Esempio n. 2
0
static void rewriteTlsVars(Module &M, std::vector<VarInfo> *TlsVars,
                           PointerType *TemplatePtrType) {
  // Set up the intrinsic that reads the thread pointer.
  Function *ReadTpFunc = Intrinsic::getDeclaration(&M, Intrinsic::nacl_read_tp);

  for (std::vector<VarInfo>::iterator VarInfo = TlsVars->begin();
       VarInfo != TlsVars->end();
       ++VarInfo) {
    GlobalVariable *Var = VarInfo->TlsVar;
    while (!Var->use_empty()) {
      Use *U = &Var->use_begin().getUse();
      Instruction *InsertPt = PhiSafeInsertPt(U);
      Value *RawThreadPtr = CallInst::Create(ReadTpFunc, "tls_raw", InsertPt);
      Value *TypedThreadPtr = new BitCastInst(RawThreadPtr, TemplatePtrType,
                                              "tls_struct", InsertPt);
      SmallVector<Value*, 3> Indexes;
      // We use -1 because we use the x86-style TLS layout in which
      // the TLS data is stored at addresses below the thread pointer.
      // This is largely because a check in nacl_irt_thread_create()
      // in irt/irt_thread.c requires the thread pointer to be a
      // self-pointer on x86-32.
      // TODO(mseaborn): I intend to remove that check because it is
      // non-portable.  In the mean time, we want PNaCl pexes to work
      // in older Chromium releases when translated to nexes.
      Indexes.push_back(ConstantInt::get(
          M.getContext(), APInt(32, -1)));
      Indexes.push_back(ConstantInt::get(
          M.getContext(), APInt(32, VarInfo->IsBss ? 1 : 0)));
      Indexes.push_back(ConstantInt::get(
          M.getContext(), APInt(32, VarInfo->TemplateIndex)));
      Value *TlsField = GetElementPtrInst::Create(TypedThreadPtr, Indexes,
                                                  "field", InsertPt);
      PhiSafeReplaceUses(U, TlsField);
    }
    VarInfo->TlsVar->eraseFromParent();
  }
}
Esempio n. 3
0
bool GenericToNVVM::runOnModule(Module &M) {
  // Create a clone of each global variable that has the default address space.
  // The clone is created with the global address space  specifier, and the pair
  // of original global variable and its clone is placed in the GVMap for later
  // use.

  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E;) {
    GlobalVariable *GV = I++;
    if (GV->getType()->getAddressSpace() == llvm::ADDRESS_SPACE_GENERIC &&
        !llvm::isTexture(*GV) && !llvm::isSurface(*GV) &&
        !GV->getName().startswith("llvm.")) {
      GlobalVariable *NewGV = new GlobalVariable(
          M, GV->getType()->getElementType(), GV->isConstant(),
          GV->getLinkage(),
          GV->hasInitializer() ? GV->getInitializer() : nullptr,
          "", GV, GV->getThreadLocalMode(), llvm::ADDRESS_SPACE_GLOBAL);
      NewGV->copyAttributesFrom(GV);
      GVMap[GV] = NewGV;
    }
  }

  // Return immediately, if every global variable has a specific address space
  // specifier.
  if (GVMap.empty()) {
    return false;
  }

  // Walk through the instructions in function defitinions, and replace any use
  // of original global variables in GVMap with a use of the corresponding
  // copies in GVMap.  If necessary, promote constants to instructions.
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    if (I->isDeclaration()) {
      continue;
    }
    IRBuilder<> Builder(I->getEntryBlock().getFirstNonPHIOrDbg());
    for (Function::iterator BBI = I->begin(), BBE = I->end(); BBI != BBE;
         ++BBI) {
      for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
           ++II) {
        for (unsigned i = 0, e = II->getNumOperands(); i < e; ++i) {
          Value *Operand = II->getOperand(i);
          if (isa<Constant>(Operand)) {
            II->setOperand(
                i, remapConstant(&M, I, cast<Constant>(Operand), Builder));
          }
        }
      }
    }
    ConstantToValueMap.clear();
  }

  // Walk through the metadata section and update the debug information
  // associated with the global variables in the default address space.
  for (Module::named_metadata_iterator I = M.named_metadata_begin(),
                                       E = M.named_metadata_end();
       I != E; I++) {
    remapNamedMDNode(&M, I);
  }

  // Walk through the global variable  initializers, and replace any use of
  // original global variables in GVMap with a use of the corresponding copies
  // in GVMap.  The copies need to be bitcast to the original global variable
  // types, as we cannot use cvta in global variable initializers.
  for (GVMapTy::iterator I = GVMap.begin(), E = GVMap.end(); I != E;) {
    GlobalVariable *GV = I->first;
    GlobalVariable *NewGV = I->second;
    ++I;
    Constant *BitCastNewGV = ConstantExpr::getPointerCast(NewGV, GV->getType());
    // At this point, the remaining uses of GV should be found only in global
    // variable initializers, as other uses have been already been removed
    // while walking through the instructions in function definitions.
    for (Value::use_iterator UI = GV->use_begin(), UE = GV->use_end();
         UI != UE;)
      (UI++)->set(BitCastNewGV);
    std::string Name = GV->getName();
    GV->removeDeadConstantUsers();
    GV->eraseFromParent();
    NewGV->setName(Name);
  }
  GVMap.clear();

  return true;
}