diff options
Diffstat (limited to 'llvm/lib/Transforms/IPO/LowerTypeTests.cpp')
-rw-r--r-- | llvm/lib/Transforms/IPO/LowerTypeTests.cpp | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp index 8bd3036f1fc3..b492b200c6d5 100644 --- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp +++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp @@ -117,6 +117,11 @@ static cl::opt<std::string> ClWriteSummary( cl::desc("Write summary to given YAML file after running pass"), cl::Hidden); +static cl::opt<bool> + ClDropTypeTests("lowertypetests-drop-type-tests", + cl::desc("Simply drop type test assume sequences"), + cl::Hidden, cl::init(false)); + bool BitSetInfo::containsGlobalOffset(uint64_t Offset) const { if (Offset < ByteOffset) return false; @@ -336,7 +341,7 @@ private: struct ScopedSaveAliaseesAndUsed { Module &M; - SmallPtrSet<GlobalValue *, 16> Used, CompilerUsed; + SmallVector<GlobalValue *, 4> Used, CompilerUsed; std::vector<std::pair<GlobalIndirectSymbol *, Function *>> FunctionAliases; ScopedSaveAliaseesAndUsed(Module &M) : M(M) { @@ -367,9 +372,8 @@ struct ScopedSaveAliaseesAndUsed { } ~ScopedSaveAliaseesAndUsed() { - appendToUsed(M, std::vector<GlobalValue *>(Used.begin(), Used.end())); - appendToCompilerUsed(M, std::vector<GlobalValue *>(CompilerUsed.begin(), - CompilerUsed.end())); + appendToUsed(M, Used); + appendToCompilerUsed(M, CompilerUsed); for (auto P : FunctionAliases) P.first->setIndirectSymbol( @@ -529,7 +533,8 @@ struct LowerTypeTests : public ModulePass { LowerTypeTests(ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary, bool DropTypeTests) : ModulePass(ID), ExportSummary(ExportSummary), - ImportSummary(ImportSummary), DropTypeTests(DropTypeTests) { + ImportSummary(ImportSummary), + DropTypeTests(DropTypeTests || ClDropTypeTests) { initializeLowerTypeTestsPass(*PassRegistry::getPassRegistry()); } @@ -1688,7 +1693,7 @@ LowerTypeTestsModule::LowerTypeTestsModule( Module &M, ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary, bool DropTypeTests) : M(M), ExportSummary(ExportSummary), ImportSummary(ImportSummary), - DropTypeTests(DropTypeTests) { + DropTypeTests(DropTypeTests || ClDropTypeTests) { assert(!(ExportSummary && ImportSummary)); Triple TargetTriple(M.getTargetTriple()); Arch = TargetTriple.getArch(); @@ -1723,7 +1728,7 @@ bool LowerTypeTestsModule::runForTesting(Module &M) { ExitOnError ExitOnErr("-lowertypetests-write-summary: " + ClWriteSummary + ": "); std::error_code EC; - raw_fd_ostream OS(ClWriteSummary, EC, sys::fs::OF_Text); + raw_fd_ostream OS(ClWriteSummary, EC, sys::fs::OF_TextWithCRLF); ExitOnErr(errorCodeToError(EC)); yaml::Output Out(OS); @@ -1791,12 +1796,16 @@ bool LowerTypeTestsModule::lower() { UI != UE;) { auto *CI = cast<CallInst>((*UI++).getUser()); // Find and erase llvm.assume intrinsics for this llvm.type.test call. - for (auto CIU = CI->use_begin(), CIUE = CI->use_end(); CIU != CIUE;) { - if (auto *AssumeCI = dyn_cast<CallInst>((*CIU++).getUser())) { - Function *F = AssumeCI->getCalledFunction(); - if (F && F->getIntrinsicID() == Intrinsic::assume) - AssumeCI->eraseFromParent(); - } + for (auto CIU = CI->use_begin(), CIUE = CI->use_end(); CIU != CIUE;) + if (auto *Assume = dyn_cast<AssumeInst>((*CIU++).getUser())) + Assume->eraseFromParent(); + // If the assume was merged with another assume, we might have a use on a + // phi (which will feed the assume). Simply replace the use on the phi + // with "true" and leave the merged assume. + if (!CI->use_empty()) { + assert(all_of(CI->users(), + [](User *U) -> bool { return isa<PHINode>(U); })); + CI->replaceAllUsesWith(ConstantInt::getTrue(M.getContext())); } CI->eraseFromParent(); } @@ -2058,6 +2067,21 @@ bool LowerTypeTestsModule::lower() { if (TypeTestFunc) { for (const Use &U : TypeTestFunc->uses()) { auto CI = cast<CallInst>(U.getUser()); + // If this type test is only used by llvm.assume instructions, it + // was used for whole program devirtualization, and is being kept + // for use by other optimization passes. We do not need or want to + // lower it here. We also don't want to rewrite any associated globals + // unnecessarily. These will be removed by a subsequent LTT invocation + // with the DropTypeTests flag set. + bool OnlyAssumeUses = !CI->use_empty(); + for (const Use &CIU : CI->uses()) { + if (isa<AssumeInst>(CIU.getUser())) + continue; + OnlyAssumeUses = false; + break; + } + if (OnlyAssumeUses) + continue; auto TypeIdMDVal = dyn_cast<MetadataAsValue>(CI->getArgOperand(1)); if (!TypeIdMDVal) |