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; }
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(); } }
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; }