Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Transforms/IPO/GlobalDCE.cpp
Show First 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | if (Comdat *C = GV.getComdat()) { | ||||
for (auto &&CM : make_range(ComdatMembers.equal_range(C))) { | for (auto &&CM : make_range(ComdatMembers.equal_range(C))) { | ||||
MarkLive(*CM.second, Updates); // Recursion depth is only two because only | MarkLive(*CM.second, Updates); // Recursion depth is only two because only | ||||
// globals in the same comdat are visited. | // globals in the same comdat are visited. | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/// Recursively iterate over the (sub-)constants in the vtable and look for | /// Recursively iterate over the (sub-)constants in the vtable and look for | ||||
/// vptrs, if their offset is within [RangeStart..RangeEnd), add them to VFuncs. | /// vptrs, if their offset is within ranges in List, add them to VFuncs. | ||||
static void FindVirtualFunctionsInVTable(Module &M, Constant *C, | static void FindVirtualFunctionsInVTable(Module &M, Constant *C, | ||||
uint64_t RangeStart, uint64_t RangeEnd, | GlobalObject::VCallVisibilityList List, | ||||
SmallPtrSet<GlobalValue *, 8> *VFuncs, | SmallPtrSet<GlobalValue *, 8> *VFuncs, | ||||
uint64_t BaseOffset = 0) { | uint64_t BaseOffset = 0) { | ||||
if (auto *GV = dyn_cast<GlobalValue>(C)) { | if (auto *GV = dyn_cast<GlobalValue>(C)) { | ||||
if (auto *F = dyn_cast<Function>(GV)) | if (auto *F = dyn_cast<Function>(GV)) | ||||
if (RangeStart <= BaseOffset && BaseOffset < RangeEnd) | for (auto Entry : List) | ||||
if (Entry.RangeStart <= BaseOffset && BaseOffset < Entry.RangeEnd) | |||||
VFuncs->insert(F); | VFuncs->insert(F); | ||||
// Do not recurse outside of the current global. | // Do not recurse outside of the current global. | ||||
return; | return; | ||||
} | } | ||||
if (auto *S = dyn_cast<ConstantStruct>(C)) { | if (auto *S = dyn_cast<ConstantStruct>(C)) { | ||||
StructType *STy = dyn_cast<StructType>(S->getType()); | StructType *STy = dyn_cast<StructType>(S->getType()); | ||||
const StructLayout *SL = M.getDataLayout().getStructLayout(STy); | const StructLayout *SL = M.getDataLayout().getStructLayout(STy); | ||||
for (auto EI : llvm::enumerate(STy->elements())) { | for (auto EI : llvm::enumerate(STy->elements())) { | ||||
auto Offset = SL->getElementOffset(EI.index()); | auto Offset = SL->getElementOffset(EI.index()); | ||||
unsigned Op = SL->getElementContainingOffset(Offset); | unsigned Op = SL->getElementContainingOffset(Offset); | ||||
FindVirtualFunctionsInVTable(M, cast<Constant>(S->getOperand(Op)), | FindVirtualFunctionsInVTable(M, cast<Constant>(S->getOperand(Op)), List, | ||||
RangeStart, RangeEnd, VFuncs, | VFuncs, BaseOffset + Offset); | ||||
BaseOffset + Offset); | |||||
} | } | ||||
} else if (auto *A = dyn_cast<ConstantArray>(C)) { | } else if (auto *A = dyn_cast<ConstantArray>(C)) { | ||||
ArrayType *ATy = A->getType(); | ArrayType *ATy = A->getType(); | ||||
auto EltSize = M.getDataLayout().getTypeAllocSize(ATy->getElementType()); | auto EltSize = M.getDataLayout().getTypeAllocSize(ATy->getElementType()); | ||||
for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) { | for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) { | ||||
FindVirtualFunctionsInVTable(M, cast<Constant>(A->getOperand(i)), | FindVirtualFunctionsInVTable(M, cast<Constant>(A->getOperand(i)), List, | ||||
RangeStart, RangeEnd, VFuncs, | VFuncs, BaseOffset + EltSize * i); | ||||
BaseOffset + EltSize * i); | |||||
} | } | ||||
} else { | } else { | ||||
for (auto &Op : C->operands()) { | for (auto &Op : C->operands()) { | ||||
FindVirtualFunctionsInVTable(M, cast<Constant>(Op), RangeStart, RangeEnd, | FindVirtualFunctionsInVTable(M, cast<Constant>(Op), List, VFuncs, | ||||
VFuncs, BaseOffset); | BaseOffset); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void GlobalDCEPass::ScanVTables(Module &M) { | void GlobalDCEPass::ScanVTables(Module &M) { | ||||
SmallVector<MDNode *, 2> Types; | SmallVector<MDNode *, 2> Types; | ||||
LLVM_DEBUG(dbgs() << "Building type info -> vtable map\n"); | LLVM_DEBUG(dbgs() << "Building type info -> vtable map\n"); | ||||
Show All 22 Lines | for (MDNode *Type : Types) { | ||||
TypeIdMap[TypeID].insert(std::make_pair(&GV, Offset)); | TypeIdMap[TypeID].insert(std::make_pair(&GV, Offset)); | ||||
} | } | ||||
// If the type corresponding to the vtable is private to this translation | // If the type corresponding to the vtable is private to this translation | ||||
// unit, we know that we can see all virtual functions which might use it, | // unit, we know that we can see all virtual functions which might use it, | ||||
// so VFE is safe. | // so VFE is safe. | ||||
if (auto GO = dyn_cast<GlobalObject>(&GV)) { | if (auto GO = dyn_cast<GlobalObject>(&GV)) { | ||||
GlobalObject::VCallVisibility TypeVis = GO->getVCallVisibility(); | GlobalObject::VCallVisibilityList List = GO->getVCallVisibility(); | ||||
// FIXME: For now, find the maximum visibility from all !vcall_visibility | |||||
// attachments, and conservatively treat all ranges with that visibility. | |||||
GlobalObject::VCallVisibility TypeVis = | |||||
GlobalObject::VCallVisibilityTranslationUnit; | |||||
for (auto Entry : List) { | |||||
TypeVis = std::min(TypeVis, Entry.Visibility); | |||||
} | |||||
if (List.empty()) | |||||
TypeVis = GlobalObject::VCallVisibilityPublic; | |||||
if (TypeVis == GlobalObject::VCallVisibilityTranslationUnit || | if (TypeVis == GlobalObject::VCallVisibilityTranslationUnit || | ||||
(LTOPostLink && | (LTOPostLink && | ||||
TypeVis == GlobalObject::VCallVisibilityLinkageUnit)) { | TypeVis == GlobalObject::VCallVisibilityLinkageUnit)) { | ||||
LLVM_DEBUG(dbgs() << GV.getName() << " is safe for VFE\n"); | LLVM_DEBUG(dbgs() << GV.getName() << " is safe for VFE\n"); | ||||
// Find and record all the vfunctions that are within the offset range | // Find and record all the vfunctions that are within the offset ranges | ||||
// specified in the !vcall_visibility attribute. | // specified in the !vcall_visibility attributes. | ||||
auto Range = GO->getVTableOffsetRange(); | |||||
SmallPtrSet<GlobalValue *, 8> VFuncs; | SmallPtrSet<GlobalValue *, 8> VFuncs; | ||||
FindVirtualFunctionsInVTable(M, GV.getInitializer(), std::get<0>(Range), | FindVirtualFunctionsInVTable(M, GV.getInitializer(), List, &VFuncs); | ||||
std::get<1>(Range), &VFuncs); | |||||
VFESafeVTablesAndFns[&GV] = VFuncs; | VFESafeVTablesAndFns[&GV] = VFuncs; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void GlobalDCEPass::ScanVTableLoad(Function *Caller, Metadata *TypeId, | void GlobalDCEPass::ScanVTableLoad(Function *Caller, Metadata *TypeId, | ||||
uint64_t CallOffset) { | uint64_t CallOffset) { | ||||
▲ Show 20 Lines • Show All 263 Lines • Show Last 20 Lines |