https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/112787
>From 7d6eb41b4eb5c4924789d31fa0f1dcd601ae46f6 Mon Sep 17 00:00:00 2001 From: Paul Kirth <paulki...@google.com> Date: Thu, 17 Oct 2024 22:32:20 +0000 Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?= =?UTF-8?q?itial=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 --- .../llvm/Transforms/IPO/LowerTypeTests.h | 5 +-- llvm/lib/Transforms/IPO/LowerTypeTests.cpp | 32 ++++++++++++------- .../LowerTypeTests/drop_type_test.ll | 19 +++++++++++ 3 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 llvm/test/Transforms/LowerTypeTests/drop_type_test.ll diff --git a/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h b/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h index eb682c437b94bc..3f5cced844062c 100644 --- a/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h +++ b/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h @@ -203,14 +203,15 @@ class LowerTypeTestsPass : public PassInfoMixin<LowerTypeTestsPass> { ModuleSummaryIndex *ExportSummary = nullptr; const ModuleSummaryIndex *ImportSummary = nullptr; bool DropTypeTests = true; + bool AlwaysDropTests = false; public: LowerTypeTestsPass() : UseCommandLine(true) {} LowerTypeTestsPass(ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary, - bool DropTypeTests = false) + bool DropTypeTests = false, bool AlwaysDropTests = false) : ExportSummary(ExportSummary), ImportSummary(ImportSummary), - DropTypeTests(DropTypeTests) {} + DropTypeTests(DropTypeTests), AlwaysDropTests(AlwaysDropTests) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp index 519a4e9314a26b..864c8cc29533a6 100644 --- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp +++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp @@ -122,6 +122,10 @@ static cl::opt<bool> ClDropTypeTests("lowertypetests-drop-type-tests", cl::desc("Simply drop type test assume sequences"), cl::Hidden, cl::init(false)); +static cl::opt<bool> + ClForceDropTypeTests("lowertypetests-force-drop-type-tests", + cl::desc("Always drop all type test sequences"), + cl::Hidden, cl::init(false)); bool BitSetInfo::containsGlobalOffset(uint64_t Offset) const { if (Offset < ByteOffset) @@ -400,6 +404,7 @@ class LowerTypeTestsModule { // Set when the client has invoked this to simply drop all type test assume // sequences. bool DropTypeTests; + bool AlwaysDropTests; Triple::ArchType Arch; Triple::OSType OS; @@ -542,7 +547,7 @@ class LowerTypeTestsModule { LowerTypeTestsModule(Module &M, ModuleAnalysisManager &AM, ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary, - bool DropTypeTests); + bool DropTypeTests, bool AlwaysDropTests); bool lower(); @@ -1828,9 +1833,11 @@ void LowerTypeTestsModule::buildBitSetsFromDisjointSet( /// Lower all type tests in this module. LowerTypeTestsModule::LowerTypeTestsModule( Module &M, ModuleAnalysisManager &AM, ModuleSummaryIndex *ExportSummary, - const ModuleSummaryIndex *ImportSummary, bool DropTypeTests) + const ModuleSummaryIndex *ImportSummary, bool DropTypeTests, + bool AlwaysDropTests) : M(M), ExportSummary(ExportSummary), ImportSummary(ImportSummary), - DropTypeTests(DropTypeTests || ClDropTypeTests) { + DropTypeTests(DropTypeTests || ClDropTypeTests), + AlwaysDropTests(AlwaysDropTests || ClForceDropTypeTests) { assert(!(ExportSummary && ImportSummary)); Triple TargetTriple(M.getTargetTriple()); Arch = TargetTriple.getArch(); @@ -1882,7 +1889,7 @@ bool LowerTypeTestsModule::runForTesting(Module &M, ModuleAnalysisManager &AM) { M, AM, ClSummaryAction == PassSummaryAction::Export ? &Summary : nullptr, ClSummaryAction == PassSummaryAction::Import ? &Summary : nullptr, - /*DropTypeTests*/ false) + /*DropTypeTests*/ false, /*AlwaysDropTests=*/false) .lower(); if (!ClWriteSummary.empty()) { @@ -1949,7 +1956,7 @@ void LowerTypeTestsModule::replaceDirectCalls(Value *Old, Value *New) { Old->replaceUsesWithIf(New, isDirectCall); } -static void dropTypeTests(Module &M, Function &TypeTestFunc) { +static void dropTypeTests(Module &M, Function &TypeTestFunc, bool AlwaysDrop) { for (Use &U : llvm::make_early_inc_range(TypeTestFunc.uses())) { auto *CI = cast<CallInst>(U.getUser()); // Find and erase llvm.assume intrinsics for this llvm.type.test call. @@ -1960,8 +1967,9 @@ static void dropTypeTests(Module &M, Function &TypeTestFunc) { // 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); })); + assert(AlwaysDrop || all_of(CI->users(), [](User *U) -> bool { + return isa<PHINode>(U); + })); CI->replaceAllUsesWith(ConstantInt::getTrue(M.getContext())); } CI->eraseFromParent(); @@ -1974,14 +1982,14 @@ bool LowerTypeTestsModule::lower() { if (DropTypeTests) { if (TypeTestFunc) - dropTypeTests(M, *TypeTestFunc); + dropTypeTests(M, *TypeTestFunc, AlwaysDropTests); // Normally we'd have already removed all @llvm.public.type.test calls, // except for in the case where we originally were performing ThinLTO but // decided not to in the backend. Function *PublicTypeTestFunc = M.getFunction(Intrinsic::getName(Intrinsic::public_type_test)); if (PublicTypeTestFunc) - dropTypeTests(M, *PublicTypeTestFunc); + dropTypeTests(M, *PublicTypeTestFunc, AlwaysDropTests); if (TypeTestFunc || PublicTypeTestFunc) { // We have deleted the type intrinsics, so we no longer have enough // information to reason about the liveness of virtual function pointers @@ -2449,9 +2457,9 @@ PreservedAnalyses LowerTypeTestsPass::run(Module &M, if (UseCommandLine) Changed = LowerTypeTestsModule::runForTesting(M, AM); else - Changed = - LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary, DropTypeTests) - .lower(); + Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary, + DropTypeTests, AlwaysDropTests) + .lower(); if (!Changed) return PreservedAnalyses::all(); return PreservedAnalyses::none(); diff --git a/llvm/test/Transforms/LowerTypeTests/drop_type_test.ll b/llvm/test/Transforms/LowerTypeTests/drop_type_test.ll new file mode 100644 index 00000000000000..23fa0b97790cf0 --- /dev/null +++ b/llvm/test/Transforms/LowerTypeTests/drop_type_test.ll @@ -0,0 +1,19 @@ +; RUN: opt -S -passes=lowertypetests -lowertypetests-force-drop-type-tests -lowertypetests-drop-type-tests < %s | FileCheck %s + +define void @func() { +entry: + %0 = tail call i1 @llvm.type.test(ptr null, metadata !"foo") + br i1 %0, label %exit, label %trap + ; CHECK: entry: + ; CHECK-NEXT: br i1 true, label %exit, label %trap + ; CHECK-NOT: @llvm.type.test + +trap: + unreachable + +exit: + ret void +} + +declare i1 @llvm.type.test(ptr, metadata) #0 +attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } >From 61ed1580ffa3d02a8b68fc2b9fba2ed176dc9241 Mon Sep 17 00:00:00 2001 From: Paul Kirth <paulki...@google.com> Date: Fri, 18 Oct 2024 01:50:53 +0000 Subject: [PATCH 2/2] Use enum option over boolean Created using spr 1.3.4 --- clang/lib/CodeGen/BackendUtil.cpp | 7 +-- .../llvm/Transforms/IPO/LowerTypeTests.h | 16 ++++-- llvm/lib/Passes/PassBuilderPipelines.cpp | 15 ++++-- llvm/lib/Transforms/IPO/LowerTypeTests.cpp | 53 +++++++++++-------- .../LowerTypeTests/drop_type_test.ll | 11 ++-- .../LowerTypeTests/drop_type_test_phi.ll | 2 +- 6 files changed, 64 insertions(+), 40 deletions(-) diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index f018130807519d..ae33554a66b6b5 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1013,9 +1013,10 @@ void EmitAssemblyHelper::RunOptimizationPipeline( if (IsThinLTOPostLink) PB.registerPipelineStartEPCallback( [](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(LowerTypeTestsPass(/*ExportSummary=*/nullptr, - /*ImportSummary=*/nullptr, - /*DropTypeTests=*/true)); + MPM.addPass(LowerTypeTestsPass( + /*ExportSummary=*/nullptr, + /*ImportSummary=*/nullptr, + /*DropTypeTests=*/lowertypetests::DropTestKind::Assume)); }); // Register callbacks to schedule sanitizer passes at the appropriate part diff --git a/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h b/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h index 3f5cced844062c..02adcd8bfd45d0 100644 --- a/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h +++ b/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h @@ -195,6 +195,13 @@ struct ByteArrayBuilder { bool isJumpTableCanonical(Function *F); +/// Specifies how to drop type tests. +enum class DropTestKind { + None, /// Do not drop type tests (default). + Assume, /// Drop only llvm.assumes using type test value. + All, /// Drop the type test and all uses. +}; + } // end namespace lowertypetests class LowerTypeTestsPass : public PassInfoMixin<LowerTypeTestsPass> { @@ -202,16 +209,17 @@ class LowerTypeTestsPass : public PassInfoMixin<LowerTypeTestsPass> { ModuleSummaryIndex *ExportSummary = nullptr; const ModuleSummaryIndex *ImportSummary = nullptr; - bool DropTypeTests = true; - bool AlwaysDropTests = false; + lowertypetests::DropTestKind DropTypeTests = + lowertypetests::DropTestKind::None; public: LowerTypeTestsPass() : UseCommandLine(true) {} LowerTypeTestsPass(ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary, - bool DropTypeTests = false, bool AlwaysDropTests = false) + lowertypetests::DropTestKind DropTypeTests = + lowertypetests::DropTestKind::None) : ExportSummary(ExportSummary), ImportSummary(ImportSummary), - DropTypeTests(DropTypeTests), AlwaysDropTests(AlwaysDropTests) {} + DropTypeTests(DropTypeTests) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index 17710eb94b6ded..6478667e22b851 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -1130,7 +1130,8 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, // post link pipeline after ICP. This is to enable usage of the type // tests in ICP sequences. if (Phase == ThinOrFullLTOPhase::ThinLTOPostLink) - MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); + MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, + lowertypetests::DropTestKind::Assume)); invokePipelineEarlySimplificationEPCallbacks(MPM, Level); @@ -1735,7 +1736,8 @@ ModulePassManager PassBuilder::buildThinLTODefaultPipeline( if (Level == OptimizationLevel::O0) { // Run a second time to clean up any type tests left behind by WPD for use // in ICP. - MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); + MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, + lowertypetests::DropTestKind::Assume)); // Drop available_externally and unreferenced globals. This is necessary // with ThinLTO in order to avoid leaving undefined references to dead // globals in the object file. @@ -1786,7 +1788,8 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, MPM.addPass(LowerTypeTestsPass(ExportSummary, nullptr)); // Run a second time to clean up any type tests left behind by WPD for use // in ICP. - MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); + MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, + lowertypetests::DropTestKind::Assume)); invokeFullLinkTimeOptimizationLastEPCallbacks(MPM, Level); @@ -1864,7 +1867,8 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, // Run a second time to clean up any type tests left behind by WPD for use // in ICP (which is performed earlier than this in the regular LTO // pipeline). - MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); + MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, + lowertypetests::DropTestKind::Assume)); invokeFullLinkTimeOptimizationLastEPCallbacks(MPM, Level); @@ -2045,7 +2049,8 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, MPM.addPass(LowerTypeTestsPass(ExportSummary, nullptr)); // Run a second time to clean up any type tests left behind by WPD for use // in ICP (which is performed earlier than this in the regular LTO pipeline). - MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); + MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, + lowertypetests::DropTestKind::Assume)); // Enable splitting late in the FullLTO post-link pipeline. if (EnableHotColdSplit) diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp index 864c8cc29533a6..1dc458a1a3bf40 100644 --- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp +++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp @@ -118,14 +118,16 @@ static cl::opt<std::string> ClWriteSummary( cl::desc("Write summary to given YAML file after running pass"), cl::Hidden); -static cl::opt<bool> +static cl::opt<DropTestKind> ClDropTypeTests("lowertypetests-drop-type-tests", - cl::desc("Simply drop type test assume sequences"), - cl::Hidden, cl::init(false)); -static cl::opt<bool> - ClForceDropTypeTests("lowertypetests-force-drop-type-tests", - cl::desc("Always drop all type test sequences"), - cl::Hidden, cl::init(false)); + cl::desc("Simply drop type test sequences"), + cl::values(clEnumValN(DropTestKind::None, "none", + "Do not drop any type tests"), + clEnumValN(DropTestKind::Assume, "assume", + "Drop type test assume sequences"), + clEnumValN(DropTestKind::All, "all", + "Drop all type test sequences")), + cl::Hidden, cl::init(DropTestKind::None)); bool BitSetInfo::containsGlobalOffset(uint64_t Offset) const { if (Offset < ByteOffset) @@ -397,14 +399,15 @@ struct ScopedSaveAliaseesAndUsed { }; class LowerTypeTestsModule { + Module &M; ModuleSummaryIndex *ExportSummary; const ModuleSummaryIndex *ImportSummary; + // Set when the client has invoked this to simply drop all type test assume // sequences. - bool DropTypeTests; - bool AlwaysDropTests; + DropTestKind DropTypeTests; Triple::ArchType Arch; Triple::OSType OS; @@ -547,7 +550,7 @@ class LowerTypeTestsModule { LowerTypeTestsModule(Module &M, ModuleAnalysisManager &AM, ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary, - bool DropTypeTests, bool AlwaysDropTests); + DropTestKind DropTypeTests); bool lower(); @@ -1833,11 +1836,10 @@ void LowerTypeTestsModule::buildBitSetsFromDisjointSet( /// Lower all type tests in this module. LowerTypeTestsModule::LowerTypeTestsModule( Module &M, ModuleAnalysisManager &AM, ModuleSummaryIndex *ExportSummary, - const ModuleSummaryIndex *ImportSummary, bool DropTypeTests, - bool AlwaysDropTests) + const ModuleSummaryIndex *ImportSummary, DropTestKind DropTypeTests) : M(M), ExportSummary(ExportSummary), ImportSummary(ImportSummary), - DropTypeTests(DropTypeTests || ClDropTypeTests), - AlwaysDropTests(AlwaysDropTests || ClForceDropTypeTests) { + DropTypeTests(ClDropTypeTests > DropTypeTests ? ClDropTypeTests + : DropTypeTests) { assert(!(ExportSummary && ImportSummary)); Triple TargetTriple(M.getTargetTriple()); Arch = TargetTriple.getArch(); @@ -1889,7 +1891,7 @@ bool LowerTypeTestsModule::runForTesting(Module &M, ModuleAnalysisManager &AM) { M, AM, ClSummaryAction == PassSummaryAction::Export ? &Summary : nullptr, ClSummaryAction == PassSummaryAction::Import ? &Summary : nullptr, - /*DropTypeTests*/ false, /*AlwaysDropTests=*/false) + /*DropTypeTests=*/DropTestKind::None) .lower(); if (!ClWriteSummary.empty()) { @@ -1956,7 +1958,8 @@ void LowerTypeTestsModule::replaceDirectCalls(Value *Old, Value *New) { Old->replaceUsesWithIf(New, isDirectCall); } -static void dropTypeTests(Module &M, Function &TypeTestFunc, bool AlwaysDrop) { +static void dropTypeTests(Module &M, Function &TypeTestFunc, + bool ShouldDropAll) { for (Use &U : llvm::make_early_inc_range(TypeTestFunc.uses())) { auto *CI = cast<CallInst>(U.getUser()); // Find and erase llvm.assume intrinsics for this llvm.type.test call. @@ -1966,8 +1969,11 @@ static void dropTypeTests(Module &M, Function &TypeTestFunc, bool AlwaysDrop) { // 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 ShouldDropAll is set, then we we need to update any remaining uses, + // regardless of the instruction type. if (!CI->use_empty()) { - assert(AlwaysDrop || all_of(CI->users(), [](User *U) -> bool { + assert(ShouldDropAll || all_of(CI->users(), [](User *U) -> bool { return isa<PHINode>(U); })); CI->replaceAllUsesWith(ConstantInt::getTrue(M.getContext())); @@ -1980,16 +1986,17 @@ bool LowerTypeTestsModule::lower() { Function *TypeTestFunc = M.getFunction(Intrinsic::getName(Intrinsic::type_test)); - if (DropTypeTests) { + if (DropTypeTests != DropTestKind::None) { + bool ShouldDropAll = DropTypeTests == DropTestKind::All; if (TypeTestFunc) - dropTypeTests(M, *TypeTestFunc, AlwaysDropTests); + dropTypeTests(M, *TypeTestFunc, ShouldDropAll); // Normally we'd have already removed all @llvm.public.type.test calls, // except for in the case where we originally were performing ThinLTO but // decided not to in the backend. Function *PublicTypeTestFunc = M.getFunction(Intrinsic::getName(Intrinsic::public_type_test)); if (PublicTypeTestFunc) - dropTypeTests(M, *PublicTypeTestFunc, AlwaysDropTests); + dropTypeTests(M, *PublicTypeTestFunc, ShouldDropAll); if (TypeTestFunc || PublicTypeTestFunc) { // We have deleted the type intrinsics, so we no longer have enough // information to reason about the liveness of virtual function pointers @@ -2457,9 +2464,9 @@ PreservedAnalyses LowerTypeTestsPass::run(Module &M, if (UseCommandLine) Changed = LowerTypeTestsModule::runForTesting(M, AM); else - Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary, - DropTypeTests, AlwaysDropTests) - .lower(); + Changed = + LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary, DropTypeTests) + .lower(); if (!Changed) return PreservedAnalyses::all(); return PreservedAnalyses::none(); diff --git a/llvm/test/Transforms/LowerTypeTests/drop_type_test.ll b/llvm/test/Transforms/LowerTypeTests/drop_type_test.ll index 23fa0b97790cf0..e1d0573924a4e7 100644 --- a/llvm/test/Transforms/LowerTypeTests/drop_type_test.ll +++ b/llvm/test/Transforms/LowerTypeTests/drop_type_test.ll @@ -1,18 +1,21 @@ -; RUN: opt -S -passes=lowertypetests -lowertypetests-force-drop-type-tests -lowertypetests-drop-type-tests < %s | FileCheck %s +; RUN: opt -S -passes=lowertypetests -lowertypetests-drop-type-tests=all < %s | FileCheck %s define void @func() { entry: %0 = tail call i1 @llvm.type.test(ptr null, metadata !"foo") br i1 %0, label %exit, label %trap - ; CHECK: entry: - ; CHECK-NEXT: br i1 true, label %exit, label %trap - ; CHECK-NOT: @llvm.type.test trap: unreachable exit: ret void + ; CHECK-LABEL: entry: + ; CHECK-NEXT: br i1 true, label %exit, label %trap + ; CHECK-LABEL: trap: + ; CHECK-NEXT: unreachable + ; CHECK-LABEL: exit: + ; CHECK-NEXT: ret void } declare i1 @llvm.type.test(ptr, metadata) #0 diff --git a/llvm/test/Transforms/LowerTypeTests/drop_type_test_phi.ll b/llvm/test/Transforms/LowerTypeTests/drop_type_test_phi.ll index 3cf4d447605da7..820865826dc7aa 100644 --- a/llvm/test/Transforms/LowerTypeTests/drop_type_test_phi.ll +++ b/llvm/test/Transforms/LowerTypeTests/drop_type_test_phi.ll @@ -1,5 +1,5 @@ ; Test to ensure dropping of type tests can handle a phi feeding the assume. -; RUN: opt -S -passes=lowertypetests -lowertypetests-drop-type-tests -mtriple=x86_64-unknown-linux-gnu %s | FileCheck %s +; RUN: opt -S -passes=lowertypetests -lowertypetests-drop-type-tests=assume -mtriple=x86_64-unknown-linux-gnu %s | FileCheck %s target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-grtev4-linux-gnu" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits