本文整理汇总了C++中GlobalVariable类的典型用法代码示例。如果您正苦于以下问题:C++ GlobalVariable类的具体用法?C++ GlobalVariable怎么用?C++ GlobalVariable使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了GlobalVariable类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: Context
void LTOCodeGenerator::applyScopeRestrictions() {
if (_scopeRestrictionsDone) return;
Module *mergedModule = _linker.getModule();
// Start off with a verification pass.
PassManager passes;
passes.add(createVerifierPass());
// mark which symbols can not be internalized
MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL);
Mangler mangler(Context, *_target->getDataLayout());
std::vector<const char*> mustPreserveList;
SmallPtrSet<GlobalValue*, 8> asmUsed;
for (Module::iterator f = mergedModule->begin(),
e = mergedModule->end(); f != e; ++f)
applyRestriction(*f, mustPreserveList, asmUsed, mangler);
for (Module::global_iterator v = mergedModule->global_begin(),
e = mergedModule->global_end(); v != e; ++v)
applyRestriction(*v, mustPreserveList, asmUsed, mangler);
for (Module::alias_iterator a = mergedModule->alias_begin(),
e = mergedModule->alias_end(); a != e; ++a)
applyRestriction(*a, mustPreserveList, asmUsed, mangler);
GlobalVariable *LLVMCompilerUsed =
mergedModule->getGlobalVariable("llvm.compiler.used");
findUsedValues(LLVMCompilerUsed, asmUsed);
if (LLVMCompilerUsed)
LLVMCompilerUsed->eraseFromParent();
if (!asmUsed.empty()) {
llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context);
std::vector<Constant*> asmUsed2;
for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(),
e = asmUsed.end(); i !=e; ++i) {
GlobalValue *GV = *i;
Constant *c = ConstantExpr::getBitCast(GV, i8PTy);
asmUsed2.push_back(c);
}
llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size());
LLVMCompilerUsed =
new llvm::GlobalVariable(*mergedModule, ATy, false,
llvm::GlobalValue::AppendingLinkage,
llvm::ConstantArray::get(ATy, asmUsed2),
"llvm.compiler.used");
LLVMCompilerUsed->setSection("llvm.metadata");
}
// Add prerequisite passes needed by SAFECode
PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/ false,
!DisableInline);
passes.add(createInternalizePass(mustPreserveList));
// apply scope restrictions
passes.run(*mergedModule);
_scopeRestrictionsDone = true;
}
示例2: jl_merge_module
// destructively move the contents of src into dest
// this assumes that the targets of the two modules are the same
// including the DataLayout and ModuleFlags (for example)
// and that there is no module-level assembly
static void jl_merge_module(Module *dest, std::unique_ptr<Module> src)
{
assert(dest != src.get());
for (Module::global_iterator I = src->global_begin(), E = src->global_end(); I != E;) {
GlobalVariable *sG = &*I;
GlobalValue *dG = dest->getNamedValue(sG->getName());
++I;
if (dG) {
if (sG->isDeclaration()) {
sG->replaceAllUsesWith(dG);
sG->eraseFromParent();
continue;
}
else {
dG->replaceAllUsesWith(sG);
dG->eraseFromParent();
}
}
sG->removeFromParent();
dest->getGlobalList().push_back(sG);
}
for (Module::iterator I = src->begin(), E = src->end(); I != E;) {
Function *sG = &*I;
GlobalValue *dG = dest->getNamedValue(sG->getName());
++I;
if (dG) {
if (sG->isDeclaration()) {
sG->replaceAllUsesWith(dG);
sG->eraseFromParent();
continue;
}
else {
dG->replaceAllUsesWith(sG);
dG->eraseFromParent();
}
}
sG->removeFromParent();
dest->getFunctionList().push_back(sG);
}
for (Module::alias_iterator I = src->alias_begin(), E = src->alias_end(); I != E;) {
GlobalAlias *sG = &*I;
GlobalValue *dG = dest->getNamedValue(sG->getName());
++I;
if (dG) {
if (!dG->isDeclaration()) { // aliases are always definitions, so this test is reversed from the above two
sG->replaceAllUsesWith(dG);
sG->eraseFromParent();
continue;
}
else {
dG->replaceAllUsesWith(sG);
dG->eraseFromParent();
}
}
sG->removeFromParent();
dest->getAliasList().push_back(sG);
}
// metadata nodes need to be explicitly merged not just copied
// so there are special passes here for each known type of metadata
NamedMDNode *sNMD = src->getNamedMetadata("llvm.dbg.cu");
if (sNMD) {
NamedMDNode *dNMD = dest->getOrInsertNamedMetadata("llvm.dbg.cu");
#ifdef LLVM35
for (NamedMDNode::op_iterator I = sNMD->op_begin(), E = sNMD->op_end(); I != E; ++I) {
dNMD->addOperand(*I);
}
#else
for (unsigned i = 0, l = sNMD->getNumOperands(); i < l; i++) {
dNMD->addOperand(sNMD->getOperand(i));
}
#endif
}
}
示例3: DL
bool AllocateDataSegment::runOnModule(Module &M) {
DataLayout DL(&M);
Type *I8 = Type::getInt8Ty(M.getContext());
Type *I32 = Type::getInt32Ty(M.getContext());
Type *IntPtrType = DL.getIntPtrType(M.getContext());
// First, we do a pass over the global variables, in which we compute
// the amount of required padding between them and consequently their
// addresses relative to the memory base of the sandbox. References to each
// global are then replaced with direct memory pointers.
uint32_t VarOffset = 0;
DenseMap<GlobalVariable*, uint32_t> VarPadding;
for (Module::global_iterator GV = M.global_begin(), E = M.global_end();
GV != E; ++GV) {
assert(GV->hasInitializer());
uint32_t Padding = getPadding(VarOffset, GV, DL);
VarPadding[GV] = Padding;
VarOffset += Padding;
GV->replaceAllUsesWith(
ConstantExpr::getIntToPtr(
ConstantInt::get(IntPtrType,
DataSegmentBaseAddress + VarOffset),
GV->getType()));
VarOffset += DL.getTypeStoreSize(GV->getType()->getPointerElementType());
}
// Using the offsets computed above, we prepare the layout and the contents
// of the desired data structure. After the type and initializer of each
// global is copied, the global is not needed any more and it is erased.
SmallVector<Type*, 10> TemplateLayout;
SmallVector<Constant*, 10> TemplateData;
for (Module::global_iterator It = M.global_begin(), E = M.global_end();
It != E; ) {
GlobalVariable *GV = It++;
uint32_t Padding = VarPadding[GV];
if (Padding > 0) {
Type *PaddingType = ArrayType::get(I8, Padding);
TemplateLayout.push_back(PaddingType);
TemplateData.push_back(ConstantAggregateZero::get(PaddingType));
}
TemplateLayout.push_back(GV->getType()->getPointerElementType());
TemplateData.push_back(GV->getInitializer());
GV->eraseFromParent();
}
// Finally, we create the struct and size global variables.
StructType *TemplateType =
StructType::create(M.getContext(), ExternalSymName_DataSegment);
TemplateType->setBody(TemplateLayout, /*isPacked=*/true);
Constant *Template = ConstantStruct::get(TemplateType, TemplateData);
new GlobalVariable(M, Template->getType(), /*isConstant=*/true,
GlobalVariable::ExternalLinkage, Template,
ExternalSymName_DataSegment);
Constant *TemplateSize =
ConstantInt::get(I32, DL.getTypeAllocSize(TemplateType));
new GlobalVariable(M, TemplateSize->getType(), /*isConstant=*/true,
GlobalVariable::ExternalLinkage, TemplateSize,
ExternalSymName_DataSegmentSize);
return true;
}
示例4: constructCheckHandlers
void InitializeSoftBound:: constructCheckHandlers(Module & module){
Type* void_ty = Type::getVoidTy(module.getContext());
Type* void_ptr_ty = PointerType::getUnqual(Type::getInt8Ty(module.getContext()));
Type* size_ty = Type::getInt64Ty(module.getContext());
module.getOrInsertFunction("__softboundcets_spatial_load_dereference_check",
void_ty, void_ptr_ty, void_ptr_ty,
void_ptr_ty, size_ty, NULL);
module.getOrInsertFunction("__softboundcets_spatial_store_dereference_check",
void_ty, void_ptr_ty, void_ptr_ty,
void_ptr_ty, size_ty, NULL);
module.getOrInsertFunction("__softboundcets_temporal_load_dereference_check",
void_ty, void_ptr_ty, size_ty,
void_ptr_ty, void_ptr_ty, NULL);
module.getOrInsertFunction("__softboundcets_temporal_store_dereference_check",
void_ty, void_ptr_ty, size_ty,
void_ptr_ty, void_ptr_ty, NULL);
Function* global_init = (Function *) module.getOrInsertFunction("__softboundcets_global_init",
void_ty, NULL);
global_init->setDoesNotThrow();
global_init->setLinkage(GlobalValue::InternalLinkage);
BasicBlock* BB = BasicBlock::Create(module.getContext(),
"entry", global_init);
Function* softboundcets_init = (Function*) module.getOrInsertFunction("__softboundcets_init", void_ty, Type::getInt32Ty(module.getContext()), NULL);
SmallVector<Value*, 8> args;
Constant * const_one = ConstantInt::get(Type::getInt32Ty(module.getContext()), 1);
args.push_back(const_one);
Instruction* ret = ReturnInst::Create(module.getContext(), BB);
CallInst::Create(softboundcets_init, args, "", ret);
Type * Int32Type = IntegerType::getInt32Ty(module.getContext());
std::vector<Constant *> CtorInits;
CtorInits.push_back(ConstantInt::get(Int32Type, 0));
CtorInits.push_back(global_init);
StructType * ST = ConstantStruct::getTypeForElements(CtorInits, false);
Constant * RuntimeCtorInit = ConstantStruct::get(ST, CtorInits);
//
// Get the current set of static global constructors and add the new ctor
// to the list.
//
std::vector<Constant *> CurrentCtors;
GlobalVariable * GVCtor = module.getNamedGlobal ("llvm.global_ctors");
if (GVCtor) {
if (Constant * C = GVCtor->getInitializer()) {
for (unsigned index = 0; index < C->getNumOperands(); ++index) {
CurrentCtors.push_back (dyn_cast<Constant>(C->getOperand (index)));
}
}
}
CurrentCtors.push_back(RuntimeCtorInit);
//
// Create a new initializer.
//
ArrayType * AT = ArrayType::get (RuntimeCtorInit-> getType(),
CurrentCtors.size());
Constant * NewInit = ConstantArray::get (AT, CurrentCtors);
//
// Create the new llvm.global_ctors global variable and remove the old one
// if it existed.
//
Value * newGVCtor = new GlobalVariable (module,
NewInit->getType(),
false,
GlobalValue::AppendingLinkage,
NewInit,
"llvm.global_ctors");
if (GVCtor) {
newGVCtor->takeName (GVCtor);
GVCtor->eraseFromParent ();
}
}
示例5: return
bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals,
Module &M, bool isConst, unsigned AddrSpace) const {
auto &DL = M.getDataLayout();
// FIXME: Find better heuristics
std::stable_sort(
Globals.begin(), Globals.end(),
[&DL](const GlobalVariable *GV1, const GlobalVariable *GV2) {
Type *Ty1 = cast<PointerType>(GV1->getType())->getElementType();
Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType();
return (DL.getTypeAllocSize(Ty1) < DL.getTypeAllocSize(Ty2));
});
// If we want to just blindly group all globals together, do so.
if (!GlobalMergeGroupByUse) {
BitVector AllGlobals(Globals.size());
AllGlobals.set();
return doMerge(Globals, AllGlobals, M, isConst, AddrSpace);
}
// If we want to be smarter, look at all uses of each global, to try to
// discover all sets of globals used together, and how many times each of
// these sets occured.
//
// Keep this reasonably efficient, by having an append-only list of all sets
// discovered so far (UsedGlobalSet), and mapping each "together-ness" unit of
// code (currently, a Function) to the set of globals seen so far that are
// used together in that unit (GlobalUsesByFunction).
//
// When we look at the Nth global, we now that any new set is either:
// - the singleton set {N}, containing this global only, or
// - the union of {N} and a previously-discovered set, containing some
// combination of the previous N-1 globals.
// Using that knowledge, when looking at the Nth global, we can keep:
// - a reference to the singleton set {N} (CurGVOnlySetIdx)
// - a list mapping each previous set to its union with {N} (EncounteredUGS),
// if it actually occurs.
// We keep track of the sets of globals used together "close enough".
struct UsedGlobalSet {
UsedGlobalSet(size_t Size) : Globals(Size), UsageCount(1) {}
BitVector Globals;
unsigned UsageCount;
};
// Each set is unique in UsedGlobalSets.
std::vector<UsedGlobalSet> UsedGlobalSets;
// Avoid repeating the create-global-set pattern.
auto CreateGlobalSet = [&]() -> UsedGlobalSet & {
UsedGlobalSets.emplace_back(Globals.size());
return UsedGlobalSets.back();
};
// The first set is the empty set.
CreateGlobalSet().UsageCount = 0;
// We define "close enough" to be "in the same function".
// FIXME: Grouping uses by function is way too aggressive, so we should have
// a better metric for distance between uses.
// The obvious alternative would be to group by BasicBlock, but that's in
// turn too conservative..
// Anything in between wouldn't be trivial to compute, so just stick with
// per-function grouping.
// The value type is an index into UsedGlobalSets.
// The default (0) conveniently points to the empty set.
DenseMap<Function *, size_t /*UsedGlobalSetIdx*/> GlobalUsesByFunction;
// Now, look at each merge-eligible global in turn.
// Keep track of the sets we already encountered to which we added the
// current global.
// Each element matches the same-index element in UsedGlobalSets.
// This lets us efficiently tell whether a set has already been expanded to
// include the current global.
std::vector<size_t> EncounteredUGS;
for (size_t GI = 0, GE = Globals.size(); GI != GE; ++GI) {
GlobalVariable *GV = Globals[GI];
// Reset the encountered sets for this global...
std::fill(EncounteredUGS.begin(), EncounteredUGS.end(), 0);
// ...and grow it in case we created new sets for the previous global.
EncounteredUGS.resize(UsedGlobalSets.size());
// We might need to create a set that only consists of the current global.
// Keep track of its index into UsedGlobalSets.
size_t CurGVOnlySetIdx = 0;
// For each global, look at all its Uses.
for (auto &U : GV->uses()) {
// This Use might be a ConstantExpr. We're interested in Instruction
// users, so look through ConstantExpr...
Use *UI, *UE;
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) {
if (CE->use_empty())
continue;
UI = &*CE->use_begin();
UE = nullptr;
//.........这里部分代码省略.........
示例6: Builder
// FIXME: Should try to pick the most likely to be profitable allocas first.
bool AMDGPUPromoteAlloca::handleAlloca(AllocaInst &I, bool SufficientLDS) {
// Array allocations are probably not worth handling, since an allocation of
// the array type is the canonical form.
if (!I.isStaticAlloca() || I.isArrayAllocation())
return false;
IRBuilder<> Builder(&I);
// First try to replace the alloca with a vector
Type *AllocaTy = I.getAllocatedType();
DEBUG(dbgs() << "Trying to promote " << I << '\n');
if (tryPromoteAllocaToVector(&I, AS))
return true; // Promoted to vector.
const Function &ContainingFunction = *I.getParent()->getParent();
CallingConv::ID CC = ContainingFunction.getCallingConv();
// Don't promote the alloca to LDS for shader calling conventions as the work
// item ID intrinsics are not supported for these calling conventions.
// Furthermore not all LDS is available for some of the stages.
switch (CC) {
case CallingConv::AMDGPU_KERNEL:
case CallingConv::SPIR_KERNEL:
break;
default:
DEBUG(dbgs() << " promote alloca to LDS not supported with calling convention.\n");
return false;
}
// Not likely to have sufficient local memory for promotion.
if (!SufficientLDS)
return false;
const AMDGPUSubtarget &ST =
TM->getSubtarget<AMDGPUSubtarget>(ContainingFunction);
unsigned WorkGroupSize = ST.getFlatWorkGroupSizes(ContainingFunction).second;
const DataLayout &DL = Mod->getDataLayout();
unsigned Align = I.getAlignment();
if (Align == 0)
Align = DL.getABITypeAlignment(I.getAllocatedType());
// FIXME: This computed padding is likely wrong since it depends on inverse
// usage order.
//
// FIXME: It is also possible that if we're allowed to use all of the memory
// could could end up using more than the maximum due to alignment padding.
uint32_t NewSize = alignTo(CurrentLocalMemUsage, Align);
uint32_t AllocSize = WorkGroupSize * DL.getTypeAllocSize(AllocaTy);
NewSize += AllocSize;
if (NewSize > LocalMemLimit) {
DEBUG(dbgs() << " " << AllocSize
<< " bytes of local memory not available to promote\n");
return false;
}
CurrentLocalMemUsage = NewSize;
std::vector<Value*> WorkList;
if (!collectUsesWithPtrTypes(&I, &I, WorkList)) {
DEBUG(dbgs() << " Do not know how to convert all uses\n");
return false;
}
DEBUG(dbgs() << "Promoting alloca to local memory\n");
Function *F = I.getParent()->getParent();
Type *GVTy = ArrayType::get(I.getAllocatedType(), WorkGroupSize);
GlobalVariable *GV = new GlobalVariable(
*Mod, GVTy, false, GlobalValue::InternalLinkage,
UndefValue::get(GVTy),
Twine(F->getName()) + Twine('.') + I.getName(),
nullptr,
GlobalVariable::NotThreadLocal,
AS.LOCAL_ADDRESS);
GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
GV->setAlignment(I.getAlignment());
Value *TCntY, *TCntZ;
std::tie(TCntY, TCntZ) = getLocalSizeYZ(Builder);
Value *TIdX = getWorkitemID(Builder, 0);
Value *TIdY = getWorkitemID(Builder, 1);
Value *TIdZ = getWorkitemID(Builder, 2);
Value *Tmp0 = Builder.CreateMul(TCntY, TCntZ, "", true, true);
Tmp0 = Builder.CreateMul(Tmp0, TIdX);
Value *Tmp1 = Builder.CreateMul(TIdY, TCntZ, "", true, true);
Value *TID = Builder.CreateAdd(Tmp0, Tmp1);
TID = Builder.CreateAdd(TID, TIdZ);
Value *Indices[] = {
//.........这里部分代码省略.........
示例7: Module
Module *llvm::CloneModule(const Module *M, ValueToValueMapTy &VMap) {
// First off, we need to create the new module.
Module *New = new Module(M->getModuleIdentifier(), M->getContext());
New->setDataLayout(M->getDataLayout());
New->setTargetTriple(M->getTargetTriple());
New->setModuleInlineAsm(M->getModuleInlineAsm());
// Loop over all of the global variables, making corresponding globals in the
// new module. Here we add them to the VMap and to the new Module. We
// don't worry about attributes or initializers, they will come later.
//
for (Module::const_global_iterator I = M->global_begin(), E = M->global_end();
I != E; ++I) {
GlobalVariable *GV = new GlobalVariable(*New,
I->getType()->getElementType(),
I->isConstant(), I->getLinkage(),
(Constant*) nullptr, I->getName(),
(GlobalVariable*) nullptr,
I->getThreadLocalMode(),
I->getType()->getAddressSpace());
GV->copyAttributesFrom(I);
VMap[I] = GV;
}
// Loop over the functions in the module, making external functions as before
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) {
Function *NF =
Function::Create(cast<FunctionType>(I->getType()->getElementType()),
I->getLinkage(), I->getName(), New);
NF->copyAttributesFrom(I);
VMap[I] = NF;
}
// Loop over the aliases in the module
for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end();
I != E; ++I) {
auto *PTy = cast<PointerType>(I->getType());
auto *GA =
GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(),
I->getLinkage(), I->getName(), New);
GA->copyAttributesFrom(I);
VMap[I] = GA;
}
// Now that all of the things that global variable initializer can refer to
// have been created, loop through and copy the global variable referrers
// over... We also set the attributes on the global now.
//
for (Module::const_global_iterator I = M->global_begin(), E = M->global_end();
I != E; ++I) {
GlobalVariable *GV = cast<GlobalVariable>(VMap[I]);
if (I->hasInitializer())
GV->setInitializer(MapValue(I->getInitializer(), VMap));
}
// Similarly, copy over function bodies now...
//
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) {
Function *F = cast<Function>(VMap[I]);
if (!I->isDeclaration()) {
Function::arg_iterator DestI = F->arg_begin();
for (Function::const_arg_iterator J = I->arg_begin(); J != I->arg_end();
++J) {
DestI->setName(J->getName());
VMap[J] = DestI++;
}
SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned.
CloneFunctionInto(F, I, VMap, /*ModuleLevelChanges=*/true, Returns);
}
}
// And aliases
for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end();
I != E; ++I) {
GlobalAlias *GA = cast<GlobalAlias>(VMap[I]);
if (const Constant *C = I->getAliasee())
GA->setAliasee(cast<GlobalObject>(MapValue(C, VMap)));
}
// And named metadata....
for (Module::const_named_metadata_iterator I = M->named_metadata_begin(),
E = M->named_metadata_end(); I != E; ++I) {
const NamedMDNode &NMD = *I;
NamedMDNode *NewNMD = New->getOrInsertNamedMetadata(NMD.getName());
for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
NewNMD->addOperand(MapValue(NMD.getOperand(i), VMap));
}
return New;
}
示例8:
void SMT12Writer::declareGlobalVariable(const GlobalVariable & v) {
m_out << ":extrafuns ((" << NameDecorator<Value>(&v)
<< " " << NameDecorator<Type>(v.getType()) << "))\n";
}
示例9: main
//.........这里部分代码省略.........
<< ExtractFuncs[i] << "'!\n";
return 1;
}
GVs.insert(GV);
}
// Extract functions via regular expression matching.
for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) {
std::string Error;
StringRef RegExStr = ExtractRegExpFuncs[i];
Regex RegEx(RegExStr);
if (!RegEx.isValid(Error)) {
errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' "
"invalid regex: " << Error;
}
bool match = false;
for (Module::iterator F = M.get()->begin(), E = M.get()->end(); F != E;
F++) {
if (RegEx.match(F->getName())) {
GVs.insert(&*F);
match = true;
}
}
if (!match) {
errs() << argv[0] << ": program doesn't contain global named '"
<< ExtractRegExpFuncs[i] << "'!\n";
return 1;
}
}
// Materialize requisite global values.
if (!DeleteFn)
for (size_t i = 0, e = GVs.size(); i != e; ++i) {
GlobalValue *GV = GVs[i];
if (GV->isMaterializable()) {
std::string ErrInfo;
if (GV->Materialize(&ErrInfo)) {
errs() << argv[0] << ": error reading input: " << ErrInfo << "\n";
return 1;
}
}
}
else {
// Deleting. Materialize every GV that's *not* in GVs.
SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end());
for (Module::global_iterator I = M->global_begin(), E = M->global_end();
I != E; ++I) {
GlobalVariable *G = I;
if (!GVSet.count(G) && G->isMaterializable()) {
std::string ErrInfo;
if (G->Materialize(&ErrInfo)) {
errs() << argv[0] << ": error reading input: " << ErrInfo << "\n";
return 1;
}
}
}
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
Function *F = I;
if (!GVSet.count(F) && F->isMaterializable()) {
std::string ErrInfo;
if (F->Materialize(&ErrInfo)) {
errs() << argv[0] << ": error reading input: " << ErrInfo << "\n";
return 1;
}
}
}
}
// In addition to deleting all other functions, we also want to spiff it
// up a little bit. Do this now.
PassManager Passes;
Passes.add(new TargetData(M.get())); // Use correct TargetData
std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end());
Passes.add(createGVExtractionPass(Gvs, DeleteFn));
if (!DeleteFn)
Passes.add(createGlobalDCEPass()); // Delete unreachable globals
Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info
Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls
std::string ErrorInfo;
tool_output_file Out(OutputFilename.c_str(), ErrorInfo,
raw_fd_ostream::F_Binary);
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
}
if (OutputAssembly)
Passes.add(createPrintModulePass(&Out.os()));
else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
Passes.add(createBitcodeWriterPass(Out.os()));
Passes.run(*M.get());
// Declare success.
Out.keep();
return 0;
}
示例10: CI
void HeterotbbTransform::rewrite_CPP(Module &M) {
// Collect initial set of hetero functions
vector<Instruction *> toDelete;
DenseMap<Function*, Function *> FunctionMap[2];
templat = NULL;
templat_join = NULL;
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
//if (isa<UnaryInst>(I))
if (!I->isDeclaration()) {
//DEBUG(dbgs() << "Func"<<*I<<"\n\n");
for (Function::iterator BBI = I->begin(), BBE = I->end(); BBI != BBE; ++BBI) {
for (BasicBlock::iterator INSNI = BBI->begin(), INSNE = BBI->end(); INSNI != INSNE; ++INSNI) {
if (isa<CallInst>(INSNI) || isa<InvokeInst>(INSNI)) {
//DEBUG(dbgs()<<*INSNI<<"\n");
CallSite CI(cast<Instruction>(INSNI));
// errs()<<"INS"<<INSNI<<"\n";
if (CI.getCalledFunction() == NULL) continue;
int type =0;
type = is_hetero_function_f(M, CI);//return a 1 for parallel_for and 2 for parallel_reduce
if (type) {
//CI->dump();
DEBUG(dbgs() << type<<":Hetero_fun "<<CI.getCalledFunction()->getName()<<"\n");
//get the kernel body
Function *f= get_hetero_func(M,CI);
//@_ZNK12diff_testingclEi
if(f!=NULL)//should never be null if the body is called.
{
DEBUG(dbgs() << " Kernel: "<<f->getName()<<"\n");
//create new function for the kernel
Function *nf=NULL;
if(FunctionMap[type-1].find(f)==FunctionMap[type-1].end()) {
nf = write_new_hetero_kernel(M,f,type);
FunctionMap[type-1][f]=nf;
DEBUG(dbgs() << " New Kernel Created: "<<nf->getName()<<" created\n\n");
/* Added by Raj to add inline attributes recursively*/
add_inline_attributes(nf);
}
else {
nf=FunctionMap[type-1][f];
DEBUG(dbgs() << " Kernel Exists: "<<nf->getName()<<" created\n\n");
}
//rewrite the hetero call site to offload
if(isa<CallInst>(INSNI))
rewrite_call_site(M,CI,nf,type);
else if(isa<InvokeInst>(INSNI)) //must be invoke
rewrite_invoke_site(M,CI,nf,type);
else {
DEBUG(dbgs()<<"ERROR\n");
}
//delete the old call site
toDelete.push_back(INSNI);
}
else {
DEBUG(dbgs() << " Parallel for/reduce hetero do not call any functions\n\n");
}
}
/*
#ifdef HETERO_GCD_H
else if(hetero_function = get_hetero_function(M, CI)) {
entry_hetero_function_set.insert(hetero_function);
#ifdef HETERO_GCD_ALLOC_TO_MALLOC
block2insnMap.insert(pair<Function *, Instruction *>(hetero_function, INSNI));
#endif
}
#endif
*/
}
}
}
}
}
while(!toDelete.empty()) {
Instruction *g = toDelete.back();
toDelete.pop_back();
// g->replaceAllUsesWith(UndefValue::get(g->getType()));
g->eraseFromParent();
}
/* delete the template functions */
if (templat_join != NULL) {
templat_join->replaceAllUsesWith(UndefValue::get(templat_join->getType()));
templat_join->eraseFromParent();
}
if (templat != NULL) {
templat->replaceAllUsesWith(UndefValue::get(templat->getType()));
templat->eraseFromParent();
}
//erase the annotation
GlobalVariable *annot = M.getGlobalVariable("opencl_metadata");
if (annot != NULL) annot->eraseFromParent();
annot = M.getGlobalVariable("opencl_metadata_type");
if (annot != NULL) annot->eraseFromParent();
annot = M.getGlobalVariable("opencl_kernel_join_name_locals");
if (annot != NULL) annot->eraseFromParent();
//.........这里部分代码省略.........
示例11: GlobalVariable
GlobalVariable *
InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
GlobalVariable *Name = Inc->getName();
auto It = RegionCounters.find(Name);
if (It != RegionCounters.end())
return It->second;
// Move the name variable to the right section. Place them in a COMDAT group
// if the associated function is a COMDAT. This will make sure that
// only one copy of counters of the COMDAT function will be emitted after
// linking.
Function *Fn = Inc->getParent()->getParent();
Comdat *ProfileVarsComdat = nullptr;
if (Fn->hasComdat())
ProfileVarsComdat = M->getOrInsertComdat(StringRef(getVarName(Inc, "vars")));
Name->setSection(getNameSection());
Name->setAlignment(1);
Name->setComdat(ProfileVarsComdat);
uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
LLVMContext &Ctx = M->getContext();
ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters);
// Create the counters variable.
auto *Counters = new GlobalVariable(*M, CounterTy, false, Name->getLinkage(),
Constant::getNullValue(CounterTy),
getVarName(Inc, "counters"));
Counters->setVisibility(Name->getVisibility());
Counters->setSection(getCountersSection());
Counters->setAlignment(8);
Counters->setComdat(ProfileVarsComdat);
RegionCounters[Inc->getName()] = Counters;
// Create data variable.
auto *NameArrayTy = Name->getType()->getPointerElementType();
auto *Int32Ty = Type::getInt32Ty(Ctx);
auto *Int64Ty = Type::getInt64Ty(Ctx);
auto *Int8PtrTy = Type::getInt8PtrTy(Ctx);
auto *Int64PtrTy = Type::getInt64PtrTy(Ctx);
Type *DataTypes[] = {Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy};
auto *DataTy = StructType::get(Ctx, makeArrayRef(DataTypes));
Constant *DataVals[] = {
ConstantInt::get(Int32Ty, NameArrayTy->getArrayNumElements()),
ConstantInt::get(Int32Ty, NumCounters),
ConstantInt::get(Int64Ty, Inc->getHash()->getZExtValue()),
ConstantExpr::getBitCast(Name, Int8PtrTy),
ConstantExpr::getBitCast(Counters, Int64PtrTy)};
auto *Data = new GlobalVariable(*M, DataTy, true, Name->getLinkage(),
ConstantStruct::get(DataTy, DataVals),
getVarName(Inc, "data"));
Data->setVisibility(Name->getVisibility());
Data->setSection(getDataSection());
Data->setAlignment(8);
Data->setComdat(ProfileVarsComdat);
// Mark the data variable as used so that it isn't stripped out.
UsedVars.push_back(Data);
return Counters;
}
示例12: DEBUG
Function* HeterotbbTransform::create_new_join(Module &M,Function *join) {
//reduce->dump();
if(!templat) {
DEBUG(dbgs()<<"NO Template Found\n");
return NULL;
}
//join_main->dump();
DEBUG(dbgs()<<"Objext size array"<<object_size_hetero<<"\n");
//create a global with 64*object/4 size
GlobalVariable *gb = M.getGlobalVariable("opencl_kernel_join_name_local_arr",true);
//gb->dump();
Value *val=gb->getOperand(0);
//if(isa<ArrayType>(val->getType()))DEBUG(dbgs()<<"YES\n");
//since we are creating an integer array, the size gets divided by 4
// Do not make it a global variable -- make it a local variable with annotation for local
int local_size = 64*object_size_hetero;
/*const*/ ArrayType *arr= ArrayType::get(Type::getInt32Ty(M.getContext()),(64*object_size_hetero)/4);
/*vector<Constant *> Initializer;
APInt zero(32,0);
for(int i=0;i<(16*object_size_hetero);i++){
Initializer.push_back(ConstantInt::get(M.getContext(),zero));
}
Constant *init = ConstantArray::get(arr, Initializer);
GlobalVariable *new_gb = new GlobalVariable(M, arr, false, GlobalVariable::InternalLinkage,init, "__hetero_local_"+join->getName()+"__local__arr",gb,false,3);
new_gb->setAlignment(gb->getAlignment());
DEBUG(dbgs()<<"Global Created\n");
new_gb->dump();
*/
vector</*const*/ Type *> params;
int temp_size=0;
object_size_hetero=0;
// void join(class.name *,class.name *)
//re-write join
const FunctionType *FTy = join->getFunctionType();
Function::arg_iterator ArgI = join->arg_begin();
// class.name *
params.push_back(PointerType::get((dyn_cast<PointerType>(ArgI->getType())->getElementType()),3));
params.push_back(PointerType::get((dyn_cast<PointerType>(ArgI->getType())->getElementType()),3));
/*const*/ Type *RetTy = FTy->getReturnType();
FunctionType *NFty = FunctionType::get(RetTy,params, false);
Function *NF=Function::Create(NFty, join->getLinkage(), join->getName()+"_inline");
NF->copyAttributesFrom(join);
#if EXPLICIT_REWRITE
copy_function(NF,join);
#else
ValueToValueMapTy VMap;
for(Function::arg_iterator FI = join->arg_begin(), FE=join->arg_end(), DI=NF->arg_begin(); FE!=FI; ++FI,++DI) {
DI->setName(FI->getName());
VMap[FI]=DI;
}
CloneFunctionWithExistingBBInto(NF, NULL, join, VMap);
#endif
//NF->removeFnAttr(Attributes::get(NF->getContext(), Attribute::NoInline));
NF->addFnAttr(Attribute::AlwaysInline);
join->getParent()->getFunctionList().insert(join, NF);
params.clear();
const FunctionType *FTemp = templat->getFunctionType();
//create a new template
for(Function::arg_iterator FI = templat->arg_begin(), FE=templat->arg_end(); FE!=FI; ++FI) {
params.push_back(FI->getType());
}
// templat->replaceUsesOfWith(reduce,NF);
RetTy = FTy->getReturnType();
NFty = FunctionType::get(RetTy,params, false);
Function *templat_copy =Function::Create(NFty, join->getLinkage(), join->getName()+"_hetero");
templat_copy->copyAttributesFrom(templat);
#if EXPLICIT_REWRITE
copy_function(templat_copy,templat);
#else
ValueToValueMapTy VMapp;
for(Function::arg_iterator FI = templat->arg_begin(), FE=templat->arg_end(), DI=templat_copy->arg_begin(); FE!=FI; ++FI,++DI) {
DI->setName(FI->getName());
VMapp[FI]=DI;
}
CloneFunctionWithExistingBBInto(templat_copy, NULL, templat, VMapp);
#endif
/* create a local variable with the following type */
Function::iterator BI = templat_copy->begin();
BasicBlock::iterator II = BI->begin();
Instruction *insn = &(*II);
Constant *l_size = ConstantInt::get(Type::getInt32Ty(M.getContext()), local_size);
Instruction *new_gb_ = new AllocaInst(arr, l_size, gb->getAlignment(), "hetero_local", insn);
//new_gb_->dump();
Value *Elts[] = {MDString::get(M.getContext(), new_gb_->getName())};
MDNode *Node = MDNode::get(M.getContext(), Elts);
new_gb_->setMetadata("local",Node);
Instruction *new_gb= CastInst::Create(Instruction::BitCast, new_gb_,
PointerType::get(arr,3), "hetero_local_cast", insn);
//new_gb->dump();
Value *Elts1[] = {MDString::get(M.getContext(), new_gb->getName())};
MDNode *Node1 = MDNode::get(M.getContext(), Elts1);
//.........这里部分代码省略.........
示例13: getOrCreateProfileComdat
GlobalVariable *
InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
GlobalVariable *NamePtr = Inc->getName();
auto It = ProfileDataMap.find(NamePtr);
PerFunctionProfileData PD;
if (It != ProfileDataMap.end()) {
if (It->second.RegionCounters)
return It->second.RegionCounters;
PD = It->second;
}
// Move the name variable to the right section. Place them in a COMDAT group
// if the associated function is a COMDAT. This will make sure that
// only one copy of counters of the COMDAT function will be emitted after
// linking.
Function *Fn = Inc->getParent()->getParent();
Comdat *ProfileVarsComdat = nullptr;
ProfileVarsComdat = getOrCreateProfileComdat(*M, *Fn, Inc);
uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
LLVMContext &Ctx = M->getContext();
ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters);
// Create the counters variable.
auto *CounterPtr =
new GlobalVariable(*M, CounterTy, false, NamePtr->getLinkage(),
Constant::getNullValue(CounterTy),
getVarName(Inc, getInstrProfCountersVarPrefix()));
CounterPtr->setVisibility(NamePtr->getVisibility());
CounterPtr->setSection(
getInstrProfSectionName(IPSK_cnts, TT.getObjectFormat()));
CounterPtr->setAlignment(8);
CounterPtr->setComdat(ProfileVarsComdat);
auto *Int8PtrTy = Type::getInt8PtrTy(Ctx);
// Allocate statically the array of pointers to value profile nodes for
// the current function.
Constant *ValuesPtrExpr = ConstantPointerNull::get(Int8PtrTy);
if (ValueProfileStaticAlloc && !needsRuntimeRegistrationOfSectionRange(*M)) {
uint64_t NS = 0;
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
NS += PD.NumValueSites[Kind];
if (NS) {
ArrayType *ValuesTy = ArrayType::get(Type::getInt64Ty(Ctx), NS);
auto *ValuesVar =
new GlobalVariable(*M, ValuesTy, false, NamePtr->getLinkage(),
Constant::getNullValue(ValuesTy),
getVarName(Inc, getInstrProfValuesVarPrefix()));
ValuesVar->setVisibility(NamePtr->getVisibility());
ValuesVar->setSection(
getInstrProfSectionName(IPSK_vals, TT.getObjectFormat()));
ValuesVar->setAlignment(8);
ValuesVar->setComdat(ProfileVarsComdat);
ValuesPtrExpr =
ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx));
}
}
// Create data variable.
auto *Int16Ty = Type::getInt16Ty(Ctx);
auto *Int16ArrayTy = ArrayType::get(Int16Ty, IPVK_Last + 1);
Type *DataTypes[] = {
#define INSTR_PROF_DATA(Type, LLVMType, Name, Init) LLVMType,
#include "llvm/ProfileData/InstrProfData.inc"
};
auto *DataTy = StructType::get(Ctx, makeArrayRef(DataTypes));
Constant *FunctionAddr = shouldRecordFunctionAddr(Fn)
? ConstantExpr::getBitCast(Fn, Int8PtrTy)
: ConstantPointerNull::get(Int8PtrTy);
Constant *Int16ArrayVals[IPVK_Last + 1];
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
Int16ArrayVals[Kind] = ConstantInt::get(Int16Ty, PD.NumValueSites[Kind]);
Constant *DataVals[] = {
#define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Init,
#include "llvm/ProfileData/InstrProfData.inc"
};
auto *Data = new GlobalVariable(*M, DataTy, false, NamePtr->getLinkage(),
ConstantStruct::get(DataTy, DataVals),
getVarName(Inc, getInstrProfDataVarPrefix()));
Data->setVisibility(NamePtr->getVisibility());
Data->setSection(getInstrProfSectionName(IPSK_data, TT.getObjectFormat()));
Data->setAlignment(INSTR_PROF_DATA_ALIGNMENT);
Data->setComdat(ProfileVarsComdat);
PD.RegionCounters = CounterPtr;
PD.DataVar = Data;
ProfileDataMap[NamePtr] = PD;
// Mark the data variable as used so that it isn't stripped out.
UsedVars.push_back(Data);
// Now that the linkage set by the FE has been passed to the data and counter
// variables, reset Name variable's linkage and visibility to private so that
// it can be removed later by the compiler.
NamePtr->setLinkage(GlobalValue::PrivateLinkage);
// Collect the referenced names to be used by emitNameData.
ReferencedNames.push_back(NamePtr);
//.........这里部分代码省略.........
示例14: GlobalVariable
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) &&
!llvm::isSampler(*GV) && !GV->getName().startswith("llvm.")) {
GlobalVariable *NewGV = new GlobalVariable(
M, GV->getValueType(), 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();
}
// Copy GVMap over to a standard value map.
ValueToValueMapTy VM;
for (auto I = GVMap.begin(), E = GVMap.end(); I != E; ++I)
VM[I->first] = I->second;
// Walk through the metadata section and update the debug information
// associated with the global variables in the default address space.
for (NamedMDNode &I : M.named_metadata()) {
remapNamedMDNode(VM, &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;
// Remove GV from the map so that it can be RAUWed. Note that
// DenseMap::erase() won't invalidate any iterators but this one.
auto Next = std::next(I);
GVMap.erase(I);
I = Next;
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.
GV->replaceAllUsesWith(BitCastNewGV);
std::string Name = GV->getName();
GV->eraseFromParent();
NewGV->setName(Name);
}
assert(GVMap.empty() && "Expected it to be empty by now");
return true;
}
示例15: FindUsedValues
bool ConstantMerge::runOnModule(Module &M) {
TD = getAnalysisIfAvailable<TargetData>();
// Find all the globals that are marked "used". These cannot be merged.
SmallPtrSet<const GlobalValue*, 8> UsedGlobals;
FindUsedValues(M.getGlobalVariable("llvm.used"), UsedGlobals);
FindUsedValues(M.getGlobalVariable("llvm.compiler.used"), UsedGlobals);
// Map unique <constants, has-unknown-alignment> pairs to globals. We don't
// want to merge globals of unknown alignment with those of explicit
// alignment. If we have TargetData, we always know the alignment.
DenseMap<PointerIntPair<Constant*, 1, bool>, GlobalVariable*> CMap;
// Replacements - This vector contains a list of replacements to perform.
SmallVector<std::pair<GlobalVariable*, GlobalVariable*>, 32> Replacements;
bool MadeChange = false;
// Iterate constant merging while we are still making progress. Merging two
// constants together may allow us to merge other constants together if the
// second level constants have initializers which point to the globals that
// were just merged.
while (1) {
// First: Find the canonical constants others will be merged with.
for (Module::global_iterator GVI = M.global_begin(), E = M.global_end();
GVI != E; ) {
GlobalVariable *GV = GVI++;
// If this GV is dead, remove it.
GV->removeDeadConstantUsers();
if (GV->use_empty() && GV->hasLocalLinkage()) {
GV->eraseFromParent();
continue;
}
// Only process constants with initializers in the default address space.
if (!GV->isConstant() || !GV->hasDefinitiveInitializer() ||
GV->getType()->getAddressSpace() != 0 || GV->hasSection() ||
// Don't touch values marked with attribute(used).
UsedGlobals.count(GV))
continue;
// This transformation is legal for weak ODR globals in the sense it
// doesn't change semantics, but we really don't want to perform it
// anyway; it's likely to pessimize code generation, and some tools
// (like the Darwin linker in cases involving CFString) don't expect it.
if (GV->isWeakForLinker())
continue;
Constant *Init = GV->getInitializer();
// Check to see if the initializer is already known.
PointerIntPair<Constant*, 1, bool> Pair(Init, hasKnownAlignment(GV));
GlobalVariable *&Slot = CMap[Pair];
// If this is the first constant we find or if the old one is local,
// replace with the current one. If the current is externally visible
// it cannot be replace, but can be the canonical constant we merge with.
if (Slot == 0 || IsBetterCannonical(*GV, *Slot))
Slot = GV;
}
// Second: identify all globals that can be merged together, filling in
// the Replacements vector. We cannot do the replacement in this pass
// because doing so may cause initializers of other globals to be rewritten,
// invalidating the Constant* pointers in CMap.
for (Module::global_iterator GVI = M.global_begin(), E = M.global_end();
GVI != E; ) {
GlobalVariable *GV = GVI++;
// Only process constants with initializers in the default address space.
if (!GV->isConstant() || !GV->hasDefinitiveInitializer() ||
GV->getType()->getAddressSpace() != 0 || GV->hasSection() ||
// Don't touch values marked with attribute(used).
UsedGlobals.count(GV))
continue;
// We can only replace constant with local linkage.
if (!GV->hasLocalLinkage())
continue;
Constant *Init = GV->getInitializer();
// Check to see if the initializer is already known.
PointerIntPair<Constant*, 1, bool> Pair(Init, hasKnownAlignment(GV));
GlobalVariable *Slot = CMap[Pair];
if (!Slot || Slot == GV)
continue;
if (!Slot->hasUnnamedAddr() && !GV->hasUnnamedAddr())
continue;
if (!GV->hasUnnamedAddr())
Slot->setUnnamedAddr(false);
// Make all uses of the duplicate constant use the canonical version.
Replacements.push_back(std::make_pair(GV, Slot));
}
//.........这里部分代码省略.........