diff --git a/Manifest.toml b/Manifest.toml index 7ebb231e..e78ee710 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -1,137 +1,159 @@ # This file is machine-generated - editing it directly is not advised -[[ArgTools]] +julia_version = "1.8.5" +manifest_format = "2.0" +project_hash = "5a0bbfc39c803f75daafe91617edc0c2dfa7877b" + +[[deps.ArgTools]] uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" +version = "1.1.1" -[[Artifacts]] +[[deps.Artifacts]] uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" -[[Base64]] +[[deps.Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" -[[CEnum]] +[[deps.CEnum]] git-tree-sha1 = "eb4cb44a499229b3b8426dcfb5dd85333951ff90" uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" version = "0.4.2" -[[Dates]] +[[deps.Dates]] deps = ["Printf"] uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" -[[Downloads]] -deps = ["ArgTools", "LibCURL", "NetworkOptions"] +[[deps.Downloads]] +deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +version = "1.6.0" + +[[deps.FileWatching]] +uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" -[[InteractiveUtils]] +[[deps.InteractiveUtils]] deps = ["Markdown"] uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" -[[JLLWrappers]] -deps = ["Preferences"] -git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1" +[[deps.JLLWrappers]] +deps = ["Artifacts", "Preferences"] +git-tree-sha1 = "7e5d6779a1e09a36db2a7b6cff50942a0a7d0fca" uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.4.1" +version = "1.5.0" -[[LLVMExtra_jll]] +[[deps.LLVMExtra_jll]] deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"] -git-tree-sha1 = "c35203c1e1002747da220ffc3c0762ce7754b08c" +git-tree-sha1 = "7ca6850ae880cc99b59b88517545f91a52020afa" uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab" -version = "0.0.23+0" +version = "0.0.25+0" -[[LazyArtifacts]] +[[deps.LazyArtifacts]] deps = ["Artifacts", "Pkg"] uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" -[[LibCURL]] +[[deps.LibCURL]] deps = ["LibCURL_jll", "MozillaCACerts_jll"] uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" +version = "0.6.3" -[[LibCURL_jll]] +[[deps.LibCURL_jll]] deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" +version = "7.84.0+0" -[[LibGit2]] +[[deps.LibGit2]] deps = ["Base64", "NetworkOptions", "Printf", "SHA"] uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" -[[LibSSH2_jll]] +[[deps.LibSSH2_jll]] deps = ["Artifacts", "Libdl", "MbedTLS_jll"] uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.10.2+0" -[[Libdl]] +[[deps.Libdl]] uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" -[[Logging]] +[[deps.Logging]] uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" -[[Markdown]] +[[deps.Markdown]] deps = ["Base64"] uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" -[[MbedTLS_jll]] +[[deps.MbedTLS_jll]] deps = ["Artifacts", "Libdl"] uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.28.0+0" -[[MozillaCACerts_jll]] +[[deps.MozillaCACerts_jll]] uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2022.2.1" -[[NetworkOptions]] +[[deps.NetworkOptions]] uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.2.0" -[[Pkg]] +[[deps.Pkg]] deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +version = "1.8.0" -[[Preferences]] +[[deps.Preferences]] deps = ["TOML"] git-tree-sha1 = "7eb1686b4f04b82f96ed7a4ea5890a4f0c7a09f1" uuid = "21216c6a-2e73-6563-6e65-726566657250" version = "1.4.0" -[[Printf]] +[[deps.Printf]] deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" -[[REPL]] +[[deps.REPL]] deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" -[[Random]] -deps = ["Serialization"] +[[deps.Random]] +deps = ["SHA", "Serialization"] uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -[[SHA]] +[[deps.SHA]] uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" -[[Serialization]] +[[deps.Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" -[[Sockets]] +[[deps.Sockets]] uuid = "6462fe0b-24de-5631-8697-dd941f90decc" -[[TOML]] +[[deps.TOML]] deps = ["Dates"] uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.0" -[[Tar]] +[[deps.Tar]] deps = ["ArgTools", "SHA"] uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" +version = "1.10.1" -[[UUIDs]] +[[deps.UUIDs]] deps = ["Random", "SHA"] uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" -[[Unicode]] +[[deps.Unicode]] uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" -[[Zlib_jll]] +[[deps.Zlib_jll]] deps = ["Libdl"] uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.2.12+3" -[[nghttp2_jll]] +[[deps.nghttp2_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" +version = "1.48.0+0" -[[p7zip_jll]] +[[deps.p7zip_jll]] deps = ["Artifacts", "Libdl"] uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +version = "17.4.0+0" diff --git a/Project.toml b/Project.toml index 54e2e8ed..da8be731 100644 --- a/Project.toml +++ b/Project.toml @@ -11,5 +11,5 @@ Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" [compat] CEnum = "0.2, 0.3, 0.4" -LLVMExtra_jll = "=0.0.23" +LLVMExtra_jll = "=0.0.25" julia = "1.8" diff --git a/deps/LLVMExtra/include/NewPM.h b/deps/LLVMExtra/include/NewPM.h index 807cfd30..5c09c8e4 100644 --- a/deps/LLVMExtra/include/NewPM.h +++ b/deps/LLVMExtra/include/NewPM.h @@ -26,19 +26,16 @@ typedef struct LLVMOpaqueModuleAnalysisManager *LLVMModuleAnalysisManagerRef; typedef struct LLVMOpaqueCGSCCAnalysisManager *LLVMCGSCCAnalysisManagerRef; typedef struct LLVMOpaqueFunctionAnalysisManager *LLVMFunctionAnalysisManagerRef; typedef struct LLVMOpaqueLoopAnalysisManager *LLVMLoopAnalysisManagerRef; -typedef struct LLVMOpaqueAAManager *LLVMAAManagerRef; LLVMModuleAnalysisManagerRef LLVMCreateNewPMModuleAnalysisManager(void); LLVMCGSCCAnalysisManagerRef LLVMCreateNewPMCGSCCAnalysisManager(void); LLVMFunctionAnalysisManagerRef LLVMCreateNewPMFunctionAnalysisManager(void); LLVMLoopAnalysisManagerRef LLVMCreateNewPMLoopAnalysisManager(void); -LLVMAAManagerRef LLVMCreateNewPMAAManager(void); void LLVMDisposeNewPMModuleAnalysisManager(LLVMModuleAnalysisManagerRef AM); void LLVMDisposeNewPMCGSCCAnalysisManager(LLVMCGSCCAnalysisManagerRef AM); void LLVMDisposeNewPMFunctionAnalysisManager(LLVMFunctionAnalysisManagerRef AM); void LLVMDisposeNewPMLoopAnalysisManager(LLVMLoopAnalysisManagerRef AM); -void LLVMDisposeNewPMAAManager(LLVMAAManagerRef AM); typedef struct LLVMOpaqueModulePassManager *LLVMModulePassManagerRef; typedef struct LLVMOpaqueCGSCCPassManager *LLVMCGSCCPassManagerRef; @@ -79,7 +76,6 @@ LLVMErrorRef LLVMPassBuilderParseModulePassPipeline(LLVMPassBuilderRef PB, LLVMM LLVMErrorRef LLVMPassBuilderParseCGSCCPassPipeline(LLVMPassBuilderRef PB, LLVMCGSCCPassManagerRef PM, const char *PipelineText, size_t PipelineTextLength); LLVMErrorRef LLVMPassBuilderParseFunctionPassPipeline(LLVMPassBuilderRef PB, LLVMFunctionPassManagerRef PM, const char *PipelineText, size_t PipelineTextLength); LLVMErrorRef LLVMPassBuilderParseLoopPassPipeline(LLVMPassBuilderRef PB, LLVMLoopPassManagerRef PM, const char *PipelineText, size_t PipelineTextLength); -LLVMErrorRef LLVMPassBuilderParseAAPipeline(LLVMPassBuilderRef PB, LLVMAAManagerRef AM, const char *PipelineText, size_t PipelineTextLength); void LLVMPassBuilderRegisterModuleAnalyses(LLVMPassBuilderRef PB, LLVMModuleAnalysisManagerRef AM); void LLVMPassBuilderRegisterCGSCCAnalyses(LLVMPassBuilderRef PB, LLVMCGSCCAnalysisManagerRef AM); @@ -95,7 +91,7 @@ void LLVMLPMAddLPM(LLVMLoopPassManagerRef PM, LLVMLoopPassManagerRef NestedPM); void LLVMMPMAddCGPM(LLVMModulePassManagerRef PM, LLVMCGSCCPassManagerRef NestedPM); void LLVMCGPMAddFPM(LLVMCGSCCPassManagerRef PM, LLVMFunctionPassManagerRef NestedPM); -void LLVMFPMAddLPM(LLVMFunctionPassManagerRef PM, LLVMLoopPassManagerRef NestedPM); +void LLVMFPMAddLPM(LLVMFunctionPassManagerRef PM, LLVMLoopPassManagerRef NestedPM, LLVMBool UseMemorySSA); void LLVMMPMAddFPM(LLVMModulePassManagerRef PM, LLVMFunctionPassManagerRef NestedPM); typedef LLVMPreservedAnalysesRef (*LLVMJuliaModulePassCallback)(LLVMModuleRef M, LLVMModuleAnalysisManagerRef AM, void *Thunk); @@ -104,6 +100,13 @@ typedef LLVMPreservedAnalysesRef (*LLVMJuliaFunctionPassCallback)(LLVMValueRef F void LLVMMPMAddJuliaPass(LLVMModulePassManagerRef PM, LLVMJuliaModulePassCallback Callback, void *Thunk); void LLVMFPMAddJuliaPass(LLVMFunctionPassManagerRef PM, LLVMJuliaFunctionPassCallback Callback, void *Thunk); +// Target Analyses +LLVMBool LLVMRegisterTargetIRAnalysis(LLVMFunctionAnalysisManagerRef FAM, LLVMTargetMachineRef TM); +LLVMBool LLVMRegisterTargetLibraryAnalysis(LLVMFunctionAnalysisManagerRef FAM, const char *Triple, size_t TripleLength); + +// Analyses +LLVMErrorRef LLVMRegisterAliasAnalyses(LLVMFunctionAnalysisManagerRef FAM, LLVMPassBuilderRef PB, LLVMTargetMachineRef TM, const char *Analyses, size_t AnalysesLength); + LLVM_C_EXTERN_C_END #endif diff --git a/deps/LLVMExtra/lib/newpm.cpp b/deps/LLVMExtra/lib/newpm.cpp index 3d2d84a1..8219561f 100644 --- a/deps/LLVMExtra/lib/newpm.cpp +++ b/deps/LLVMExtra/lib/newpm.cpp @@ -3,12 +3,14 @@ #if LLVM_VERSION_MAJOR >= 15 #include +#include #include #include #include #include +#include -#include "llvm/Support/CBindingWrapping.h" +#include using llvm::wrap; using llvm::unwrap; @@ -43,7 +45,6 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::ModuleAnalysisManager, LLVMModuleAnalys DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::CGSCCAnalysisManager, LLVMCGSCCAnalysisManagerRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::FunctionAnalysisManager, LLVMFunctionAnalysisManagerRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::LoopAnalysisManager, LLVMLoopAnalysisManagerRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::AAManager, LLVMAAManagerRef) LLVMModuleAnalysisManagerRef LLVMCreateNewPMModuleAnalysisManager(void) { return wrap(new llvm::ModuleAnalysisManager()); @@ -57,9 +58,6 @@ LLVMFunctionAnalysisManagerRef LLVMCreateNewPMFunctionAnalysisManager(void) { LLVMLoopAnalysisManagerRef LLVMCreateNewPMLoopAnalysisManager(void) { return wrap(new llvm::LoopAnalysisManager()); } -LLVMAAManagerRef LLVMCreateNewPMAAManager(void) { - return wrap(new llvm::AAManager()); -} void LLVMDisposeNewPMModuleAnalysisManager(LLVMModuleAnalysisManagerRef AM) { delete unwrap(AM); @@ -73,9 +71,6 @@ void LLVMDisposeNewPMFunctionAnalysisManager(LLVMFunctionAnalysisManagerRef AM) void LLVMDisposeNewPMLoopAnalysisManager(LLVMLoopAnalysisManagerRef AM) { delete unwrap(AM); } -void LLVMDisposeNewPMAAManager(LLVMAAManagerRef AM) { - delete unwrap(AM); -} DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::ModulePassManager, LLVMModulePassManagerRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::CGSCCPassManager, LLVMCGSCCPassManagerRef) @@ -158,9 +153,6 @@ LLVMErrorRef LLVMPassBuilderParseFunctionPassPipeline(LLVMPassBuilderRef PB, LLV LLVMErrorRef LLVMPassBuilderParseLoopPassPipeline(LLVMPassBuilderRef PB, LLVMLoopPassManagerRef PM, const char *PipelineText, size_t PipelineTextLength) { return wrap(unwrap(PB)->parsePassPipeline(*unwrap(PM), llvm::StringRef(PipelineText, PipelineTextLength))); } -LLVMErrorRef LLVMPassBuilderParseAAPipeline(LLVMPassBuilderRef PB, LLVMAAManagerRef AM, const char *PipelineText, size_t PipelineTextLength) { - return wrap(unwrap(PB)->parseAAPipeline(*unwrap(AM), llvm::StringRef(PipelineText, PipelineTextLength))); -} void LLVMPassBuilderRegisterModuleAnalyses(LLVMPassBuilderRef PB, LLVMModuleAnalysisManagerRef AM) { unwrap(PB)->registerModuleAnalyses(*unwrap(AM)); @@ -198,8 +190,8 @@ void LLVMMPMAddCGPM(LLVMModulePassManagerRef PM, LLVMCGSCCPassManagerRef NestedP void LLVMCGPMAddFPM(LLVMCGSCCPassManagerRef PM, LLVMFunctionPassManagerRef NestedPM) { unwrap(PM)->addPass(llvm::createCGSCCToFunctionPassAdaptor(std::move(*unwrap(NestedPM)))); } -void LLVMFPMAddLPM(LLVMFunctionPassManagerRef PM, LLVMLoopPassManagerRef NestedPM) { - unwrap(PM)->addPass(llvm::createFunctionToLoopPassAdaptor(std::move(*unwrap(NestedPM)))); +void LLVMFPMAddLPM(LLVMFunctionPassManagerRef PM, LLVMLoopPassManagerRef NestedPM, LLVMBool UseMemorySSA) { + unwrap(PM)->addPass(llvm::createFunctionToLoopPassAdaptor(std::move(*unwrap(NestedPM)), UseMemorySSA)); } void LLVMMPMAddFPM(LLVMModulePassManagerRef PM, LLVMFunctionPassManagerRef NestedPM) { unwrap(PM)->addPass(llvm::createModuleToFunctionPassAdaptor(std::move(*unwrap(NestedPM)))); @@ -239,4 +231,25 @@ void LLVMFPMAddJuliaPass(LLVMFunctionPassManagerRef PM, LLVMJuliaFunctionPassCal unwrap(PM)->addPass(JuliaCustomFunctionPass(Callback, Thunk)); } +// Target Analyses + +LLVMBool LLVMRegisterTargetIRAnalysis(LLVMFunctionAnalysisManagerRef FAM, LLVMTargetMachineRef TM) { + return unwrap(FAM)->registerPass([&] { return llvm::TargetIRAnalysis(unwrap(TM)->getTargetIRAnalysis()); }); +} +LLVMBool LLVMRegisterTargetLibraryAnalysis(LLVMFunctionAnalysisManagerRef FAM, const char *Triple, size_t TripleLength) { + return unwrap(FAM)->registerPass([&] { return llvm::TargetLibraryAnalysis(llvm::TargetLibraryInfoImpl(llvm::Triple(llvm::StringRef(Triple, TripleLength)))); }); +} + +// Alias Analyses +LLVMErrorRef LLVMRegisterAliasAnalyses(LLVMFunctionAnalysisManagerRef FAM, LLVMPassBuilderRef PB, LLVMTargetMachineRef TM, const char *Analyses, size_t AnalysesLength) { + llvm::AAManager AA; + auto err = unwrap(PB)->parseAAPipeline(AA, llvm::StringRef(Analyses, AnalysesLength)); + if (err) + return wrap(std::move(err)); + if (TM) + unwrap(TM)->registerDefaultAliasAnalyses(AA); + unwrap(FAM)->registerPass([&] { return std::move(AA); }); + return LLVMErrorSuccess; +} + #endif diff --git a/lib/libLLVM_extra.jl b/lib/libLLVM_extra.jl index 130d4cd1..8000b3ba 100644 --- a/lib/libLLVM_extra.jl +++ b/lib/libLLVM_extra.jl @@ -510,10 +510,6 @@ mutable struct LLVMOpaqueLoopAnalysisManager end const LLVMLoopAnalysisManagerRef = Ptr{LLVMOpaqueLoopAnalysisManager} -mutable struct LLVMOpaqueAAManager end - -const LLVMAAManagerRef = Ptr{LLVMOpaqueAAManager} - function LLVMCreateNewPMModuleAnalysisManager() ccall((:LLVMCreateNewPMModuleAnalysisManager, libLLVMExtra), LLVMModuleAnalysisManagerRef, ()) end @@ -530,10 +526,6 @@ function LLVMCreateNewPMLoopAnalysisManager() ccall((:LLVMCreateNewPMLoopAnalysisManager, libLLVMExtra), LLVMLoopAnalysisManagerRef, ()) end -function LLVMCreateNewPMAAManager() - ccall((:LLVMCreateNewPMAAManager, libLLVMExtra), LLVMAAManagerRef, ()) -end - function LLVMDisposeNewPMModuleAnalysisManager(AM) ccall((:LLVMDisposeNewPMModuleAnalysisManager, libLLVMExtra), Cvoid, (LLVMModuleAnalysisManagerRef,), AM) end @@ -550,10 +542,6 @@ function LLVMDisposeNewPMLoopAnalysisManager(AM) ccall((:LLVMDisposeNewPMLoopAnalysisManager, libLLVMExtra), Cvoid, (LLVMLoopAnalysisManagerRef,), AM) end -function LLVMDisposeNewPMAAManager(AM) - ccall((:LLVMDisposeNewPMAAManager, libLLVMExtra), Cvoid, (LLVMAAManagerRef,), AM) -end - mutable struct LLVMOpaqueModulePassManager end const LLVMModulePassManagerRef = Ptr{LLVMOpaqueModulePassManager} @@ -666,10 +654,6 @@ function LLVMPassBuilderParseLoopPassPipeline(PB, PM, PipelineText, PipelineText ccall((:LLVMPassBuilderParseLoopPassPipeline, libLLVMExtra), LLVMErrorRef, (LLVMPassBuilderRef, LLVMLoopPassManagerRef, Cstring, Csize_t), PB, PM, PipelineText, PipelineTextLength) end -function LLVMPassBuilderParseAAPipeline(PB, AM, PipelineText, PipelineTextLength) - ccall((:LLVMPassBuilderParseAAPipeline, libLLVMExtra), LLVMErrorRef, (LLVMPassBuilderRef, LLVMAAManagerRef, Cstring, Csize_t), PB, AM, PipelineText, PipelineTextLength) -end - function LLVMPassBuilderRegisterModuleAnalyses(PB, AM) ccall((:LLVMPassBuilderRegisterModuleAnalyses, libLLVMExtra), Cvoid, (LLVMPassBuilderRef, LLVMModuleAnalysisManagerRef), PB, AM) end @@ -714,8 +698,8 @@ function LLVMCGPMAddFPM(PM, NestedPM) ccall((:LLVMCGPMAddFPM, libLLVMExtra), Cvoid, (LLVMCGSCCPassManagerRef, LLVMFunctionPassManagerRef), PM, NestedPM) end -function LLVMFPMAddLPM(PM, NestedPM) - ccall((:LLVMFPMAddLPM, libLLVMExtra), Cvoid, (LLVMFunctionPassManagerRef, LLVMLoopPassManagerRef), PM, NestedPM) +function LLVMFPMAddLPM(PM, NestedPM, UseMemorySSA) + ccall((:LLVMFPMAddLPM, libLLVMExtra), Cvoid, (LLVMFunctionPassManagerRef, LLVMLoopPassManagerRef, LLVMBool), PM, NestedPM, UseMemorySSA) end function LLVMMPMAddFPM(PM, NestedPM) @@ -735,5 +719,16 @@ end function LLVMFPMAddJuliaPass(PM, Callback, Thunk) ccall((:LLVMFPMAddJuliaPass, libLLVMExtra), Cvoid, (LLVMFunctionPassManagerRef, LLVMJuliaFunctionPassCallback, Ptr{Cvoid}), PM, Callback, Thunk) end -end # v"15" <= version() +function LLVMRegisterTargetIRAnalysis(FAM, TM) + ccall((:LLVMRegisterTargetIRAnalysis, libLLVMExtra), LLVMBool, (LLVMFunctionAnalysisManagerRef, LLVMTargetMachineRef), FAM, TM) +end + +function LLVMRegisterTargetLibraryAnalysis(FAM, Triple, TripleLength) + ccall((:LLVMRegisterTargetLibraryAnalysis, libLLVMExtra), LLVMBool, (LLVMFunctionAnalysisManagerRef, Cstring, Csize_t), FAM, Triple, TripleLength) +end + +function LLVMRegisterAliasAnalyses(FAM, PB, TM, Analyses, AnalysesLength) + ccall((:LLVMRegisterAliasAnalyses, libLLVMExtra), LLVMErrorRef, (LLVMFunctionAnalysisManagerRef, LLVMPassBuilderRef, LLVMTargetMachineRef, Cstring, Csize_t), FAM, PB, TM, Analyses, AnalysesLength) +end +end # v"15" <= version() diff --git a/lib/libLLVM_julia.jl b/lib/libLLVM_julia.jl index a937fe8f..8b446e12 100644 --- a/lib/libLLVM_julia.jl +++ b/lib/libLLVM_julia.jl @@ -60,6 +60,19 @@ function LLVMAddCPUFeaturesPass(PM) ccall(:LLVMExtraAddCPUFeaturesPass,Cvoid,(LLVMPassManagerRef,), PM) end +if VERSION >= v"1.10.0-DEV.1622" + +function LLVMRegisterJuliaPassBuilderCallbacks(PB) + ccall(:jl_register_passbuilder_callbacks,Cvoid,(LLVMPassBuilderRef,), PB) +end + +function LLVMAddJuliaPipelinePass(PM, PB, Speedup, Size, lower_intrinsics, dump_native, external_use, llvm_only) + ccall(:jl_build_newpm_pipeline,Cvoid,(LLVMModulePassManagerRef,LLVMPassBuilderRef,Cint,Cint,Cint,Cint,Cint,Cint), PM, PB, Speedup, Size, lower_intrinsics, dump_native, external_use, llvm_only) +end + +end + + if VERSION >= v"1.10.0-DEV.1395" mutable struct JLOpaqueJuliaOJIT end @@ -110,4 +123,4 @@ function JLJITGetIRCompileLayer(JIT) ccall(:JLJITGetIRCompileLayer, LLVMOrcIRCompileLayerRef, (JuliaOJITRef,), JIT) end -end # VERSION >= v"1.10.0-DEV.1395" +end diff --git a/src/interop.jl b/src/interop.jl index 01b857ec..ea5922f0 100644 --- a/src/interop.jl +++ b/src/interop.jl @@ -10,4 +10,8 @@ include("interop/pointer.jl") include("interop/utils.jl") include("interop/intrinsics.jl") +if LLVM.has_newpm() && VERSION >= v"1.10.0-DEV.1622" + include("interop/newpm.jl") +end + end diff --git a/src/interop/newpm.jl b/src/interop/newpm.jl new file mode 100644 index 00000000..8587ea80 --- /dev/null +++ b/src/interop/newpm.jl @@ -0,0 +1,79 @@ +import ..LLVM: @module_pass, @function_pass, @loop_pass +import ..LLVM: is_module_pass, is_cgscc_pass, is_function_pass, is_loop_pass +import ..LLVM: pass_string, options_string, add! + +@module_pass "CPUFeatures" CPUFeaturesPass +@module_pass "RemoveNI" RemoveNIPass +@module_pass "LowerSIMDLoop" LowerSIMDLoopPass +@module_pass "RemoveJuliaAddrspaces" RemoveJuliaAddrspacesPass +@module_pass "RemoveAddrspaces" RemoveAddrspacesPass +@static if VERSION < v"1.11.0-DEV.208" + @module_pass "FinalLowerGC" FinalLowerGCPass +end + +struct MultiVersioningPassOptions + external::Core.Bool +end +MultiVersioningPassOptions(; external::Core.Bool=false) = MultiVersioningPassOptions(external) +options_string(options::MultiVersioningPassOptions) = options.external ? "" : "" +@module_pass "JuliaMultiVersioning" MultiVersioningPass MultiVersioningPassOptions + +struct LowerPTLSPassOptions + imaging::Core.Bool +end +LowerPTLSPassOptions(; imaging::Core.Bool=false) = LowerPTLSPassOptions(imaging) +options_string(options::LowerPTLSPassOptions) = options.imaging ? "" : "" +@module_pass "LowerPTLSPass" LowerPTLSPass LowerPTLSPassOptions + +@function_pass "DemoteFloat16" DemoteFloat16Pass +@function_pass "CombineMulAdd" CombineMulAddPass +@function_pass "LateLowerGCFrame" LateLowerGCPass +@function_pass "AllocOpt" AllocOptPass +@function_pass "PropagateJuliaAddrspaces" PropagateJuliaAddrspacesPass +@function_pass "LowerExcHandlers" LowerExcHandlersPass +@static if VERSION >= v"1.11.0-DEV.208" + @function_pass "FinalLowerGC" FinalLowerGCPass +end + +struct GCInvariantVerifierPassOptions + strong::Core.Bool +end +GCInvariantVerifierPassOptions(; strong::Core.Bool=false) = + GCInvariantVerifierPassOptions(strong) +options_string(options::GCInvariantVerifierPassOptions) = options.strong ? "" : "" +@function_pass "GCInvariantVerifier" GCInvariantVerifierPass GCInvariantVerifierPassOptions + +@loop_pass "JuliaLICM" JuliaLICMPass + +# The entire Julia pipeline +struct JuliaPipelinePassOptions + opt_level::Int + lower_intrinsics::Core.Bool + dump_native::Core.Bool + external_use::Core.Bool + llvm_only::Core.Bool +end +JuliaPipelinePassOptions(; opt_level=Base.JLOptions().opt_level, + lower_intrinsics::Core.Bool=true, + dump_native::Core.Bool=false, external_use::Core.Bool=false, + llvm_only::Core.Bool=false) = + JuliaPipelinePassOptions(convert(Int, opt_level), lower_intrinsics, dump_native, + external_use, llvm_only) +function options_string(options::JuliaPipelinePassOptions) + optlevel = "O$(options.opt_level)" + lower_intrinsics = options.lower_intrinsics ? "lower_intrinsics" : "no_lower_intrinsics" + dump_native = options.dump_native ? "dump_native" : "no_dump_native" + external_use = options.external_use ? "external_use" : "no_external_use" + llvm_only = options.llvm_only ? "llvm_only" : "no_llvm_only" + "<$optlevel;$lower_intrinsics;$dump_native;$external_use;$llvm_only>" +end +@module_pass "julia" JuliaPipelinePass JuliaPipelinePassOptions + +# We specialize the add! here because if we go through the PassBuilder parser, +# Julia won't insert the PassBuilder's callbacks in the right spots. +# Using the specific method call here allows insertion of those callbacks. +function add!(pm::NewPMModulePassManager, pb::PassBuilder, pass::JuliaPipelinePass) + API.LLVMAddJuliaPipelinePass(pm, pb, pass.options.opt_level, 0, + pass.options.lower_intrinsics, pass.options.dump_native, + pass.options.external_use, pass.options.llvm_only) +end diff --git a/src/newpm.jl b/src/newpm.jl index cf3464bd..52107d0d 100644 --- a/src/newpm.jl +++ b/src/newpm.jl @@ -3,5 +3,6 @@ include("newpm/analysismanager.jl") include("newpm/passmanager.jl") include("newpm/instrumentation.jl") include("newpm/passbuilder.jl") +include("newpm/analyses.jl") include("newpm/passes.jl") include("newpm/custompass.jl") diff --git a/src/newpm/analyses.jl b/src/newpm/analyses.jl new file mode 100644 index 00000000..c0d7f01e --- /dev/null +++ b/src/newpm/analyses.jl @@ -0,0 +1,77 @@ +export NewPMAnalysis, NewPMAliasAnalysis + +export add!, analysis_string, analysis_managers + +abstract type NewPMAnalysis end +abstract type NewPMAliasAnalysis end + +macro alias_analysis(analysis_name, class_name) + quote + export $class_name + struct $class_name <: NewPMAliasAnalysis end + @eval analysis_string(::$class_name) = $analysis_name + end +end + +analysis_string(aa::AAManager) = join(aa.aas, ",") + +Base.show(io::IO, analysis::NewPMAnalysis) = print(io, analysis_string(analysis)) +Base.show(io::IO, aa::AAManager) = print(io, analysis_string(aa)) + +# Module Alias Analysis +@alias_analysis "globals-aa" GlobalsAA + +# Function Alias Analysis +@alias_analysis "basic-aa" BasicAA +@alias_analysis "cfl-anders-aa" CFLAndersAA +@alias_analysis "cfl-steens-aa" CFLSteensAA +@alias_analysis "objc-arc-aa" ObjCARCAA +@alias_analysis "scev-aa" SCEVAA +@alias_analysis "scoped-noalias-aa" ScopedNoAliasAA +@alias_analysis "tbaa" TypeBasedAA + +add!(am::AAManager, aa::NewPMAliasAnalysis) = push!(am.aas, analysis_string(aa)) +add!(am::AAManager, aas::AbstractVector{<:NewPMAliasAnalysis}) = + append!(am.aas, analysis_string.(aas)) +add!(am::AAManager, tm::TargetMachine) = am.tm = tm + +export TargetIRAnalysis, TargetLibraryAnalysis + +struct TargetIRAnalysis + tm::TargetMachine +end +analysis_string(::TargetIRAnalysis) = "target-ir-analysis" + +struct TargetLibraryAnalysis + triple::String +end +analysis_string(::TargetLibraryAnalysis) = "target-library-analysis" + +add!(fam::FunctionAnalysisManager, analysis::TargetIRAnalysis) = + convert(Core.Bool, API.LLVMRegisterTargetIRAnalysis(fam, analysis.tm)) +add!(fam::FunctionAnalysisManager, analysis::TargetLibraryAnalysis) = + convert(Core.Bool, API.LLVMRegisterTargetLibraryAnalysis(fam, analysis.triple, + length(analysis.triple))) + +function analysis_managers(f::Core.Function, pb::Union{Nothing,PassBuilder}=nothing, + tm::Union{Nothing,TargetMachine}=nothing, + aa_stack::AbstractVector{<:NewPMAliasAnalysis}=NewPMAliasAnalysis[]) + @dispose lam=LoopAnalysisManager() fam=FunctionAnalysisManager() cam=CGSCCAnalysisManager() mam=ModuleAnalysisManager() begin + if !isempty(aa_stack) + add!(fam, AAManager) do aam + add!(aam, aa_stack) + if !isnothing(tm) + add!(aam, tm) + end + end + end + if !isnothing(tm) + add!(fam, TargetIRAnalysis(tm)) + add!(fam, TargetLibraryAnalysis(triple(tm))) + end + if !isnothing(pb) + register!(pb, lam, fam, cam, mam) + end + f(lam, fam, cam, mam) + end +end diff --git a/src/newpm/analysismanager.jl b/src/newpm/analysismanager.jl index 614be415..3d5e5124 100644 --- a/src/newpm/analysismanager.jl +++ b/src/newpm/analysismanager.jl @@ -1,6 +1,6 @@ export AnalysisManager, ModuleAnalysisManager, CGSCCAnalysisManager, FunctionAnalysisManager, LoopAnalysisManager, AAManager -export dispose, analysis_managers +export dispose, add! abstract type AnalysisManager end @@ -12,36 +12,35 @@ end ref::API.LLVMCGSCCAnalysisManagerRef roots::Vector{Any} end -@checked struct FunctionAnalysisManager <: AnalysisManager +mutable struct AAManager + aas::Vector{String} + tm::Union{Nothing,TargetMachine} +end +@checked mutable struct FunctionAnalysisManager <: AnalysisManager ref::API.LLVMFunctionAnalysisManagerRef + aa::Union{Nothing,AAManager} roots::Vector{Any} end @checked struct LoopAnalysisManager <: AnalysisManager ref::API.LLVMLoopAnalysisManagerRef roots::Vector{Any} end -@checked struct AAManager - ref::API.LLVMAAManagerRef - roots::Vector{Any} -end Base.unsafe_convert(::Type{API.LLVMModuleAnalysisManagerRef}, am::ModuleAnalysisManager) = am.ref Base.unsafe_convert(::Type{API.LLVMCGSCCAnalysisManagerRef}, am::CGSCCAnalysisManager) = am.ref Base.unsafe_convert(::Type{API.LLVMFunctionAnalysisManagerRef}, am::FunctionAnalysisManager) = am.ref Base.unsafe_convert(::Type{API.LLVMLoopAnalysisManagerRef}, am::LoopAnalysisManager) = am.ref -Base.unsafe_convert(::Type{API.LLVMAAManagerRef}, am::AAManager) = am.ref ModuleAnalysisManager() = ModuleAnalysisManager(API.LLVMCreateNewPMModuleAnalysisManager(), []) CGSCCAnalysisManager() = CGSCCAnalysisManager(API.LLVMCreateNewPMCGSCCAnalysisManager(), []) -FunctionAnalysisManager() = FunctionAnalysisManager(API.LLVMCreateNewPMFunctionAnalysisManager(), []) +FunctionAnalysisManager() = FunctionAnalysisManager(API.LLVMCreateNewPMFunctionAnalysisManager(), nothing, []) LoopAnalysisManager() = LoopAnalysisManager(API.LLVMCreateNewPMLoopAnalysisManager(), []) -AAManager() = AAManager(API.LLVMCreateNewPMAAManager(), []) +AAManager() = AAManager([], nothing) dispose(mam::ModuleAnalysisManager) = API.LLVMDisposeNewPMModuleAnalysisManager(mam) dispose(cgmam::CGSCCAnalysisManager) = API.LLVMDisposeNewPMCGSCCAnalysisManager(cgmam) dispose(fam::FunctionAnalysisManager) = API.LLVMDisposeNewPMFunctionAnalysisManager(fam) dispose(lam::LoopAnalysisManager) = API.LLVMDisposeNewPMLoopAnalysisManager(lam) -dispose(aam::AAManager) = API.LLVMDisposeNewPMAAManager(aam) function ModuleAnalysisManager(f::Core.Function, args...; kwargs...) am = ModuleAnalysisManager(args...; kwargs...) @@ -75,17 +74,22 @@ function LoopAnalysisManager(f::Core.Function, args...; kwargs...) dispose(am) end end -function AAManager(f::Core.Function, args...; kwargs...) - am = AAManager(args...; kwargs...) - try - f(am) - finally - dispose(am) + +function add!(fam::FunctionAnalysisManager, aa::AAManager) + if isnothing(fam.aa) + fam.aa = aa + return true + else + return false end end -function analysis_managers(f::Core.Function) - @dispose lam=LoopAnalysisManager() fam=FunctionAnalysisManager() cgam=CGSCCAnalysisManager() mam=ModuleAnalysisManager() begin - f(lam, fam, cgam, mam) +function add!(f::Core.Function, fam::FunctionAnalysisManager, ::Type{AAManager}) + if !isnothing(fam.aa) + return false end + aa = AAManager() + f(aa) + add!(fam, aa) + return true end diff --git a/src/newpm/custompass.jl b/src/newpm/custompass.jl index 128c97f3..feb0e2b7 100644 --- a/src/newpm/custompass.jl +++ b/src/newpm/custompass.jl @@ -1,4 +1,4 @@ -export add! +export add!, legacy2newpm function module_pass_callback_impl(mod, mam, thunk) m = Module(mod) @@ -13,7 +13,7 @@ end function function_pass_callback_impl(fun, fam, thunk) f = Function(fun) - am = FunctionAnalysisManager(fam, Any[]) + am = FunctionAnalysisManager(fam, nothing, Any[]) pass = Base.unsafe_pointer_to_objref(thunk)::Ref{Core.Function} preserved = unsafe_run() do pa = pass[](f, am)::PreservedAnalyses @@ -35,3 +35,11 @@ function add!(f::Core.Function, fpm::NewPMFunctionPassManager) push!(fpm.roots, cb) GC.@preserve cb API.LLVMFPMAddJuliaPass(fpm, julia_function_pass_callback, Base.pointer_from_objref(cb)) end + +legacy2newpm(f::Core.Function) = (ir, am) -> begin + if f(ir) + return no_analyses_preserved() + else + return all_analyses_preserved() + end +end diff --git a/src/newpm/passbuilder.jl b/src/newpm/passbuilder.jl index 27519937..f42e704e 100644 --- a/src/newpm/passbuilder.jl +++ b/src/newpm/passbuilder.jl @@ -4,16 +4,39 @@ export dispose, register!, cross_register_proxies!, parse! @checked struct PassBuilder ref::API.LLVMPassBuilderRef + owned_pic::Union{Nothing,PassInstrumentationCallbacks} roots::Vector{Any} end Base.unsafe_convert(::Type{API.LLVMPassBuilderRef}, pb::PassBuilder) = pb.ref -PassBuilder(tm::TargetMachine) = PassBuilder(API.LLVMCreatePassBuilder(tm, C_NULL), []) -PassBuilder(tm::TargetMachine, pic::PassInstrumentationCallbacks) = PassBuilder(API.LLVMCreatePassBuilder(tm, pic), []) -PassBuilder() = PassBuilder(API.LLVMCreatePassBuilder(C_NULL, C_NULL), []) +function create_passbuilder_internal(tm, pic) + pb = API.LLVMCreatePassBuilder(tm, pic) + if VERSION >= v"1.10.0-DEV.1622" + API.LLVMRegisterJuliaPassBuilderCallbacks(pb) + end + pb +end -dispose(pb::PassBuilder) = API.LLVMDisposePassBuilder(pb) +struct RequestStandardInstrumentationCallbacks; end +function PassBuilder(tm=nothing, pic=RequestStandardInstrumentationCallbacks()) + # if no callbacks are requested, we default to LLVM's standard instrumentation, + # unless the user explicitly requests no instrumentation by passing pic=nothing. + if pic == RequestStandardInstrumentationCallbacks() + owned_pic = pic = StandardInstrumentationCallbacks() + else + owned_pic = nothing + end + pb = create_passbuilder_internal(something(tm, C_NULL), something(pic, C_NULL)) + PassBuilder(pb, owned_pic, []) +end + +function dispose(pb::PassBuilder) + API.LLVMDisposePassBuilder(pb) + if !isnothing(pb.owned_pic) + dispose(pb.owned_pic) + end +end function PassBuilder(f::Core.Function, args...; kwargs...) pb = PassBuilder(args...; kwargs...) @@ -24,14 +47,29 @@ function PassBuilder(f::Core.Function, args...; kwargs...) end end -register!(pb::PassBuilder, am::ModuleAnalysisManager) = API.LLVMPassBuilderRegisterModuleAnalyses(pb, am) -register!(pb::PassBuilder, am::CGSCCAnalysisManager) = API.LLVMPassBuilderRegisterCGSCCAnalyses(pb, am) -register!(pb::PassBuilder, am::FunctionAnalysisManager) = API.LLVMPassBuilderRegisterFunctionAnalyses(pb, am) -register!(pb::PassBuilder, am::LoopAnalysisManager) = API.LLVMPassBuilderRegisterLoopAnalyses(pb, am) +register!(pb::PassBuilder, am::ModuleAnalysisManager) = + API.LLVMPassBuilderRegisterModuleAnalyses(pb, am) +register!(pb::PassBuilder, am::CGSCCAnalysisManager) = + API.LLVMPassBuilderRegisterCGSCCAnalyses(pb, am) +register!(pb::PassBuilder, am::LoopAnalysisManager) = + API.LLVMPassBuilderRegisterLoopAnalyses(pb, am) +# FunctionAnalysisManager is special because we can build alias analysis pipelines on top of it +function register!(pb::PassBuilder, am::FunctionAnalysisManager) + if !isnothing(am.aa) + pipeline = analysis_string(am.aa) + tm = something(am.aa.tm, C_NULL) + @check API.LLVMRegisterAliasAnalyses(am, pb, tm, pipeline, length(pipeline)) + end + API.LLVMPassBuilderRegisterFunctionAnalyses(pb, am) +end -cross_register_proxies!(pb::PassBuilder, lam::LoopAnalysisManager, fam::FunctionAnalysisManager, cgam::CGSCCAnalysisManager, mam::ModuleAnalysisManager) = API.LLVMPassBuilderCrossRegisterProxies(pb, lam, fam, cgam, mam) +cross_register_proxies!(pb::PassBuilder, lam::LoopAnalysisManager, + fam::FunctionAnalysisManager, cgam::CGSCCAnalysisManager, + mam::ModuleAnalysisManager) = + API.LLVMPassBuilderCrossRegisterProxies(pb, lam, fam, cgam, mam) -function register!(pb::PassBuilder, lam::LoopAnalysisManager, fam::FunctionAnalysisManager, cgam::CGSCCAnalysisManager, mam::ModuleAnalysisManager) +function register!(pb::PassBuilder, lam::LoopAnalysisManager, fam::FunctionAnalysisManager, + cgam::CGSCCAnalysisManager, mam::ModuleAnalysisManager) register!(pb, lam) register!(pb, fam) register!(pb, cgam) @@ -39,7 +77,32 @@ function register!(pb::PassBuilder, lam::LoopAnalysisManager, fam::FunctionAnaly cross_register_proxies!(pb, lam, fam, cgam, mam) end -parse!(pb::PassBuilder, pm::NewPMModulePassManager, s::String) = @check API.LLVMPassBuilderParseModulePassPipeline(pb, pm, s, length(s)) -parse!(pb::PassBuilder, pm::NewPMCGSCCPassManager, s::String) = @check API.LLVMPassBuilderParseCGSCCPassPipeline(pb, pm, s, length(s)) -parse!(pb::PassBuilder, pm::NewPMFunctionPassManager, s::String) = @check API.LLVMPassBuilderParseFunctionPassPipeline(pb, pm, s, length(s)) -parse!(pb::PassBuilder, pm::NewPMLoopPassManager, s::String) = @check API.LLVMPassBuilderParseLoopPassPipeline(pb, pm, s, length(s)) +parse!(pb::PassBuilder, pm::NewPMModulePassManager, s::String) = + @check API.LLVMPassBuilderParseModulePassPipeline(pb, pm, s, length(s)) +parse!(pb::PassBuilder, pm::NewPMCGSCCPassManager, s::String) = + @check API.LLVMPassBuilderParseCGSCCPassPipeline(pb, pm, s, length(s)) +parse!(pb::PassBuilder, pm::NewPMFunctionPassManager, s::String) = + @check API.LLVMPassBuilderParseFunctionPassPipeline(pb, pm, s, length(s)) +parse!(pb::PassBuilder, pm::NewPMLoopPassManager, s::String) = + @check API.LLVMPassBuilderParseLoopPassPipeline(pb, pm, s, length(s)) + +function passbuilder(pm::NewPMPassManager)::PassBuilder + if isnothing(pm.pb) + throw(ArgumentError("PassManager was not initialized with a PassBuilder, please provide a PassBuilder to add!.")) + end + pm.pb +end + + +## pipelines + +# we generally don't need to define pipelines here, as we can reuse LLVM's, +# but the AA stack needs to be passed explicitly, so define a default one here. + +function default_aa_pipeline(; global_analyses::Core.Bool=false) + aa_stack = NewPMAliasAnalysis[BasicAA(), ScopedNoAliasAA(), TypeBasedAA()] + if global_analyses + push!(aa_stack, GlobalsAA()) + end + return aa_stack +end diff --git a/src/newpm/passes.jl b/src/newpm/passes.jl index e9636a9d..44826411 100644 --- a/src/newpm/passes.jl +++ b/src/newpm/passes.jl @@ -1,7 +1,8 @@ export NewPMPass, NewPMLLVMPass export is_module_pass, is_cgscc_pass, is_function_pass, is_loop_pass, pass_string -# Export all the passes + +# helper functionality macro module_pass(pass_name, class_name) quote @@ -17,9 +18,9 @@ macro module_pass(pass_name, class_name, params) export $params export $class_name struct $class_name <: NewPMLLVMPass - options::$params + options::$(esc(params)) end - @eval $class_name() = $class_name($params()) + @eval $class_name(; kwargs...) = $class_name($params(; kwargs...)) @eval is_module_pass(::Type{$class_name}) = true @eval pass_string(pass::$class_name) = $pass_name * options_string(pass.options) end @@ -39,9 +40,9 @@ macro cgscc_pass(pass_name, class_name, params) export $params export $class_name struct $class_name <: NewPMLLVMPass - options::$params + options::$(esc(params)) end - @eval $class_name() = $class_name($params()) + @eval $class_name(; kwargs...) = $class_name($params(; kwargs...)) @eval is_cgscc_pass(::Type{$class_name}) = true @eval pass_string(pass::$class_name) = $pass_name * options_string(pass.options) end @@ -61,9 +62,9 @@ macro function_pass(pass_name, class_name, params) export $params export $class_name struct $class_name <: NewPMLLVMPass - options::$params + options::$(esc(params)) end - @eval $class_name() = $class_name($params()) + @eval $class_name(; kwargs...) = $class_name($params(; kwargs...)) @eval is_function_pass(::Type{$class_name}) = true @eval pass_string(pass::$class_name) = $pass_name * options_string(pass.options) end @@ -83,9 +84,9 @@ macro loop_pass(pass_name, class_name, params) export $params export $class_name struct $class_name <: NewPMLLVMPass - options::$params + options::$(esc(params)) end - @eval $class_name() = $class_name($params()) + @eval $class_name(; kwargs...) = $class_name($params(; kwargs...)) @eval is_loop_pass(::Type{$class_name}) = true @eval pass_string(pass::$class_name) = $pass_name * options_string(pass.options) end @@ -101,7 +102,8 @@ is_loop_pass(::Type{<:NewPMLLVMPass}) = false Base.show(io::IO, pass::NewPMLLVMPass) = print(io, pass_string(pass)) -# Module passes + +# module passes @module_pass "always-inline" AlwaysInlinerPass @module_pass "attributor" AttributorPass @@ -186,20 +188,18 @@ Base.show(io::IO, pass::NewPMLLVMPass) = print(io, pass_string(pass)) @module_pass "poison-checking" PoisonCheckingPass @module_pass "pseudo-probe-update" PseudoProbeUpdatePass -# Module Passes With Params - struct LoopExtractorPassOptions single::Core.Bool end -LoopExtractorPassOptions() = LoopExtractorPassOptions(false) -options_string(options::LoopExtractorPassOptions) = ifelse(options.single, "", "") +LoopExtractorPassOptions(; single::Core.Bool = false) = LoopExtractorPassOptions(single) +options_string(options::LoopExtractorPassOptions) = options.single ? "" : "" @module_pass "loop-extract" LoopExtractorPass LoopExtractorPassOptions struct HWAddressSanitizerPassOptions kernel::Core.Bool recover::Core.Bool end -HWAddressSanitizerPassOptions() = HWAddressSanitizerPassOptions(false, false) +HWAddressSanitizerPassOptions(; kernel::Core.Bool = false, recover::Core.Bool = false) = HWAddressSanitizerPassOptions(kernel, recover) function options_string(options::HWAddressSanitizerPassOptions) s = String[] if options.kernel @@ -219,11 +219,14 @@ end struct ModuleAddressSanitizerPassOptions kernel::Core.Bool end -ModuleAddressSanitizerPassOptions() = ModuleAddressSanitizerPassOptions(false) -options_string(options::ModuleAddressSanitizerPassOptions) = ifelse(options.kernel, "", "") +ModuleAddressSanitizerPassOptions(; kernel::Core.Bool = false) = + ModuleAddressSanitizerPassOptions(kernel) +options_string(options::ModuleAddressSanitizerPassOptions) = + options.kernel ? "" : "" @module_pass "asan-module" ModuleAddressSanitizerPass ModuleAddressSanitizerPassOptions -# CGSCC Passes + +# CGSCC passes @cgscc_pass "argpromotion" ArgumentPromotionPass # @cgscc_pass "invalidate" InvalidateAllAnalysesPass @@ -233,23 +236,24 @@ is_cgscc_pass(::Type{InvalidateAllAnalysesPass}) = true @cgscc_pass "openmp-opt-cgscc" OpenMPOptCGSCCPass @cgscc_pass "no-op-cgscc" NoOpCGSCCPass -# CGSCC Passes With Params - struct InlinerPassOptions onlymandatory::Core.Bool end -InlinerPassOptions() = InlinerPassOptions(false) -options_string(options::InlinerPassOptions) = ifelse(options.onlymandatory, "", "") +InlinerPassOptions(; onlymandatory::Core.Bool = false) = InlinerPassOptions(onlymandatory) +options_string(options::InlinerPassOptions) = + options.onlymandatory ? "" : "" @cgscc_pass "inline" InlinerPass InlinerPassOptions struct CoroSplitPassOptions reusestorage::Core.Bool end -CoroSplitPassOptions() = CoroSplitPassOptions(false) -options_string(options::CoroSplitPassOptions) = ifelse(options.reusestorage, "", "") +CoroSplitPassOptions(; reusestorage::Core.Bool = false) = CoroSplitPassOptions(reusestorage) +options_string(options::CoroSplitPassOptions) = + options.reusestorage ? "" : "" @cgscc_pass "coro-split" CoroSplitPass CoroSplitPassOptions -# Function Passes + +# function passes @function_pass "aa-eval" AAEvaluator @function_pass "adce" ADCEPass @@ -388,63 +392,73 @@ is_function_pass(::Type{VerifierPass}) = true @function_pass "tsan" ThreadSanitizerPass @function_pass "memprof" MemProfilerPass -# Function Passes With Params - struct EarlyCSEPassOptions memssa::Core.Bool end -EarlyCSEPassOptions() = EarlyCSEPassOptions(false) -options_string(options::EarlyCSEPassOptions) = ifelse(options.memssa, "", "") +EarlyCSEPassOptions(; memssa::Core.Bool = false) = EarlyCSEPassOptions(memssa) +options_string(options::EarlyCSEPassOptions) = options.memssa ? "" : "" @function_pass "early-cse" EarlyCSEPass EarlyCSEPassOptions struct EntryExitInstrumenterPassOptions postinline::Core.Bool end -EntryExitInstrumenterPassOptions() = EntryExitInstrumenterPassOptions(true) -options_string(options::EntryExitInstrumenterPassOptions) = ifelse(options.postinline, "", "") +EntryExitInstrumenterPassOptions(; postinline::Core.Bool = false) = + EntryExitInstrumenterPassOptions(postinline) +options_string(options::EntryExitInstrumenterPassOptions) = + options.postinline ? "" : "" @function_pass "ee-instrument" EntryExitInstrumenterPass EntryExitInstrumenterPassOptions struct LowerMatrixIntrinsicsPassOptions minimal::Core.Bool end -LowerMatrixIntrinsicsPassOptions() = LowerMatrixIntrinsicsPassOptions(false) -options_string(options::LowerMatrixIntrinsicsPassOptions) = ifelse(options.minimal, "", "") +LowerMatrixIntrinsicsPassOptions(; minimal::Core.Bool = false) = + LowerMatrixIntrinsicsPassOptions(minimal) +options_string(options::LowerMatrixIntrinsicsPassOptions) = + options.minimal ? "" : "" @function_pass "lower-matrix-intrinsics" LowerMatrixIntrinsicsPass LowerMatrixIntrinsicsPassOptions -struct LoopUnrollPassOptions - speedup::Int - fullunrollmax::Union{Nothing, Int} - partial::Union{Nothing, Core.Bool} - peeling::Union{Nothing, Core.Bool} - profilepeeling::Union{Nothing, Core.Bool} - runtime::Union{Nothing, Core.Bool} - upperbound::Union{Nothing, Core.Bool} -end -LoopUnrollPassOptions() = LoopUnrollPassOptions(2, nothing, nothing, nothing, nothing, nothing, nothing) -function options_string(options::LoopUnrollPassOptions) +struct LoopUnrollOptions + opt_level::Int + full_unroll_max_count::Union{Nothing, Int} + allow_partial::Union{Nothing, Core.Bool} + allow_peeling::Union{Nothing, Core.Bool} + allow_profile_based_peeling::Union{Nothing, Core.Bool} + allow_runtime::Union{Nothing, Core.Bool} + allow_upper_bound::Union{Nothing, Core.Bool} +end +LoopUnrollOptions(; opt_level::Int = 2, + full_unroll_max_count::Union{Nothing, Int} = nothing, + allow_partial::Union{Nothing, Bool} = nothing, + allow_peeling::Union{Nothing, Bool} = nothing, + allow_profile_based_peeling::Union{Nothing, Bool} = nothing, + allow_runtime::Union{Nothing, Bool} = nothing, + allow_upper_bound::Union{Nothing, Bool} = nothing) = + LoopUnrollOptions(opt_level, full_unroll_max_count, allow_partial, allow_peeling, + allow_profile_based_peeling, allow_runtime, allow_upper_bound) +function options_string(options::LoopUnrollOptions) final_options = String[] - push!(final_options, "O$(options.speedup)") - if options.fullunrollmax !== nothing - push!(final_options, "full-unroll-max=$(options.fullunrollmax)") + push!(final_options, "O$(options.opt_level)") + if options.full_unroll_max_count !== nothing + push!(final_options, "full-unroll-max=$(options.full_unroll_max_count)") end - if options.partial !== nothing - push!(final_options, ifelse(options.partial, "partial", "no-partial")) + if options.allow_partial !== nothing + push!(final_options, options.allow_partial ? "partial" : "no-partial") end - if options.peeling !== nothing - push!(final_options, ifelse(options.peeling, "peeling", "no-peeling")) + if options.allow_peeling !== nothing + push!(final_options, options.allow_peeling ? "peeling" : "no-peeling") end - if options.profilepeeling !== nothing - push!(final_options, ifelse(options.profilepeeling, "profile-peeling", "no-profile-peeling")) + if options.allow_profile_based_peeling !== nothing + push!(final_options, options.allow_profile_based_peeling ? "profile-peeling" : "no-profile-peeling") end - if options.runtime !== nothing - push!(final_options, ifelse(options.runtime, "runtime", "no-runtime")) + if options.allow_runtime !== nothing + push!(final_options, options.allow_runtime ? "runtime" : "no-runtime") end - if options.upperbound !== nothing - push!(final_options, ifelse(options.upperbound, "upperbound", "no-upperbound")) + if options.allow_upper_bound !== nothing + push!(final_options, options.allow_upper_bound ? "upperbound" : "no-upperbound") end "<" * join(final_options, ";") * ">" end -@function_pass "loop-unroll" LoopUnrollPass LoopUnrollPassOptions +@function_pass "loop-unroll" LoopUnrollPass LoopUnrollOptions struct MemorySanitizerPassOptions recover::Core.Bool @@ -452,7 +466,11 @@ struct MemorySanitizerPassOptions eagerchecks::Core.Bool trackorigins::Int end -MemorySanitizerPassOptions() = MemorySanitizerPassOptions(false, false, false, 0) +MemorySanitizerPassOptions(; recover::Core.Bool = false, + kernel::Core.Bool = false, + eagerchecks::Core.Bool = false, + trackorigins::Int = 0) = + MemorySanitizerPassOptions(recover, kernel, eagerchecks, trackorigins) function options_string(options::MemorySanitizerPassOptions) final_options = String[] if options.recover @@ -470,24 +488,33 @@ end @function_pass "msan" MemorySanitizerPass MemorySanitizerPassOptions struct SimplifyCFGPassOptions - forwardswitchcond::Core.Bool - switchrangetoicmp::Core.Bool - switchtolookup::Core.Bool - keeploops::Core.Bool - hoistcommoninsts::Core.Bool - sinkcommoninsts::Core.Bool - bonusinstthreshold::Int -end -SimplifyCFGPassOptions() = SimplifyCFGPassOptions(false, false, false, true, false, false, 1) + forward_switch_cond_to_phi::Core.Bool + convert_switch_range_to_icmp::Core.Bool + convert_switch_to_lookup_table::Core.Bool + keep_loops::Core.Bool + hoist_common_insts::Core.Bool + sink_common_inst::Core.Bool + bonus_inst_threshold::Int +end +SimplifyCFGPassOptions(; forward_switch_cond_to_phi::Core.Bool = false, + convert_switch_range_to_icmp::Core.Bool = false, + convert_switch_to_lookup_table::Core.Bool = false, + keep_loops::Core.Bool = true, + hoist_common_insts::Core.Bool = false, + sink_common_inst::Core.Bool = false, + bonus_inst_threshold::Int = 1) = + SimplifyCFGPassOptions(forward_switch_cond_to_phi, convert_switch_range_to_icmp, + convert_switch_to_lookup_table, keep_loops, + hoist_common_insts, sink_common_inst, bonus_inst_threshold) function options_string(options::SimplifyCFGPassOptions) - forward = ifelse(options.forwardswitchcond, "forward-switch-cond", "no-forward-switch-cond") - s2i = ifelse(options.switchrangetoicmp, "switch-range-to-icmp", "no-switch-range-to-icmp") - s2l = ifelse(options.switchtolookup, "switch-to-lookup", "no-switch-to-lookup") - keeploops = ifelse(options.keeploops, "keep-loops", "no-keep-loops") - hoist = ifelse(options.hoistcommoninsts, "hoist-common-insts", "no-hoist-common-insts") - sink = ifelse(options.sinkcommoninsts, "sink-common-insts", "no-sink-common-insts") - bonus = "bonus-inst-threshold=$(options.bonusinstthreshold)" - "<" * join([forward, s2i, s2l, keeploops, hoist, sink, bonus], ";") * ">" + forward = options.forward_switch_cond_to_phi ? "forward-switch-cond" : "no-forward-switch-cond" + s2i = options.convert_switch_range_to_icmp ? "switch-range-to-icmp" : "no-switch-range-to-icmp" + s2l = options.convert_switch_to_lookup_table ? "switch-to-lookup" : "no-switch-to-lookup" + keep_loops = options.keep_loops ? "keep-loops" : "no-keep-loops" + hoist = options.hoist_common_insts ? "hoist-common-insts" : "no-hoist-common-insts" + sink = options.sink_common_inst ? "sink-common-insts" : "no-sink-common-insts" + bonus = "bonus-inst-threshold=$(options.bonus_inst_threshold)" + "<" * join([forward, s2i, s2l, keep_loops, hoist, sink, bonus], ";") * ">" end @function_pass "simplifycfg" SimplifyCFGPass SimplifyCFGPassOptions @@ -495,10 +522,14 @@ struct LoopVectorizePassOptions interleaveforcedonly::Core.Bool vectorizeforcedonly::Core.Bool end -LoopVectorizePassOptions() = LoopVectorizePassOptions(false, false) +LoopVectorizePassOptions(; interleaveforcedonly::Core.Bool = false, + vectorizeforcedonly::Core.Bool = false) = + LoopVectorizePassOptions(interleaveforcedonly, vectorizeforcedonly) function options_string(options::LoopVectorizePassOptions) - interleave = ifelse(options.interleaveforcedonly, "interleave-forced-only", "no-interleave-forced-only") - vectorize = ifelse(options.vectorizeforcedonly, "vectorize-forced-only", "no-vectorize-forced-only") + interleave = options.interleaveforcedonly ? "interleave-forced-only" : + "no-interleave-forced-only" + vectorize = options.vectorizeforcedonly ? "vectorize-forced-only" : + "no-vectorize-forced-only" "<" * join([interleave, vectorize], ";") * ">" end @function_pass "loop-vectorize" LoopVectorizePass LoopVectorizePassOptions @@ -506,8 +537,10 @@ end struct MergedLoadStoreMotionPassOptions splitfooterbb::Core.Bool end -MergedLoadStoreMotionPassOptions() = MergedLoadStoreMotionPassOptions(false) -options_string(options::MergedLoadStoreMotionPassOptions) = ifelse(options.splitfooterbb, "", "") +MergedLoadStoreMotionPassOptions(; splitfooterbb::Core.Bool = false) = + MergedLoadStoreMotionPassOptions(splitfooterbb) +options_string(options::MergedLoadStoreMotionPassOptions) = + options.splitfooterbb ? "" : "" @function_pass "mldst-motion" MergedLoadStoreMotionPass MergedLoadStoreMotionPassOptions struct GVNPassOptions @@ -516,7 +549,11 @@ struct GVNPassOptions allowloadpresplitbackedge::Union{Nothing, Core.Bool} allowmemdep::Union{Nothing, Core.Bool} end -GVNPassOptions() = GVNPassOptions(nothing, nothing, nothing, nothing) +GVNPassOptions(; allowpre::Union{Nothing, Core.Bool} = nothing, + allowloadpre::Union{Nothing, Core.Bool} = nothing, + allowloadpresplitbackedge::Union{Nothing, Core.Bool} = nothing, + allowmemdep::Union{Nothing, Core.Bool} = nothing) = + GVNPassOptions(allowpre, allowloadpre, allowloadpresplitbackedge, allowmemdep) function options_string(options::GVNPassOptions) final_options = String[] if options.allowpre !== nothing @@ -554,20 +591,22 @@ end struct StackLifetimePrinterPassOptions must::Core.Bool end -StackLifetimePrinterPassOptions() = StackLifetimePrinterPassOptions(false) -function options_string(options::StackLifetimePrinterPassOptions) - ifelse(options.must, "", "") -end +StackLifetimePrinterPassOptions(; must::Core.Bool = false) = + StackLifetimePrinterPassOptions(must) +options_string(options::StackLifetimePrinterPassOptions) = + options.must ? "" : "" @function_pass "print" StackLifetimePrinterPass StackLifetimePrinterPassOptions -# Loop Nest Passes + +# loop nest passes @loop_pass "loop-flatten" LoopFlattenPass @loop_pass "loop-interchange" LoopInterchangePass @loop_pass "loop-unroll-and-jam" LoopUnrollAndJamPass @loop_pass "no-op-loopnest" NoOpLoopNestPass -# Loop Passes + +# loop passes @loop_pass "canon-freeze" CanonicalizeFreezeInLoopsPass @loop_pass "dot-ddg" DDGDotPrinterPass @@ -595,16 +634,15 @@ is_loop_pass(::Type{GuardWideningPass}) = true @loop_pass "loop-reroll" LoopRerollPass @loop_pass "loop-versioning-licm" LoopVersioningLICMPass -# Loop Passes With Params - struct SimpleLoopUnswitchPassOptions nontrivial::Core.Bool trivial::Core.Bool end -SimpleLoopUnswitchPassOptions() = SimpleLoopUnswitchPassOptions(false, true) +SimpleLoopUnswitchPassOptions(; nontrivial::Core.Bool = false, trivial::Core.Bool = true) = + SimpleLoopUnswitchPassOptions(nontrivial, trivial) function options_string(options::SimpleLoopUnswitchPassOptions) - nontrivial = ifelse(options.nontrivial, "nontrivial", "no-nontrivial") - trivial = ifelse(options.trivial, "trivial", "no-trivial") + nontrivial = options.nontrivial ? "nontrivial" : "no-nontrivial" + trivial = options.trivial ? "trivial" : "no-trivial" "<$nontrivial;$trivial>" end @loop_pass "simple-loop-unswitch" SimpleLoopUnswitchPass SimpleLoopUnswitchPassOptions @@ -612,46 +650,114 @@ end struct LICMPassOptions allowspeculation::Core.Bool end -LICMPassOptions() = LICMPassOptions(true) -options_string(options::LICMPassOptions) = ifelse(options.allowspeculation, "", "") +LICMPassOptions(; allowspeculation::Core.Bool = true) = LICMPassOptions(allowspeculation) +options_string(options::LICMPassOptions) = + options.allowspeculation ? "" : "" @loop_pass "licm" LICMPass LICMPassOptions const LNICMPassOptions = LICMPassOptions @loop_pass "lnicm" LNICMPass LNICMPassOptions -# Add methods + +# add methods function add!(pm::NewPMModulePassManager, pb::PassBuilder, pass::NewPMLLVMPass) if !is_module_pass(typeof(pass)) - error("Pass $pass is not a module pass") + throw(ArgumentError("Pass $pass is not a module pass")) end parse!(pb, pm, pass_string(pass)) end function add!(pm::NewPMCGSCCPassManager, pb::PassBuilder, pass::NewPMLLVMPass) if !is_cgscc_pass(typeof(pass)) - error("Pass $pass is not a cgscc pass") + throw(ArgumentError("Pass $pass is not a cgscc pass")) end parse!(pb, pm, pass_string(pass)) end function add!(pm::NewPMFunctionPassManager, pb::PassBuilder, pass::NewPMLLVMPass) if !is_function_pass(typeof(pass)) - error("Pass $pass is not a function pass") + throw(ArgumentError("Pass $pass is not a function pass")) end parse!(pb, pm, pass_string(pass)) end function add!(pm::NewPMLoopPassManager, pb::PassBuilder, pass::NewPMLLVMPass) if !is_loop_pass(typeof(pass)) - error("Pass $pass is not a loop pass") + throw(ArgumentError("Pass $pass is not a loop pass")) end parse!(pb, pm, pass_string(pass)) end function add!(pm::NewPMPassManager, pass::NewPMLLVMPass) - if isnothing(pm.pb) - error("PassManager was not initialized with a PassBuilder, please provide a PassBuilder to add!.") + add!(pm, passbuilder(pm), pass) +end + +function run!(pm::NewPMModulePassManager, m::Module, + tm::Union{Nothing,TargetMachine} = nothing, + aa_stack::AbstractVector{<:NewPMAliasAnalysis} = default_aa_pipeline(global_analyses=true)) + pb = passbuilder(pm) + analysis_managers(pb, tm, aa_stack) do lam, fam, cam, mam + dispose(run!(pm, m, mam)) + end +end + +function run!(pm::NewPMFunctionPassManager, f::Function, + tm::Union{Nothing,TargetMachine} = nothing, + aa_stack::AbstractVector{<:NewPMAliasAnalysis} = default_aa_pipeline()) + pb = passbuilder(pm) + analysis_managers(pb, tm, aa_stack) do lam, fam, cam, mam + dispose(run!(pm, f, fam)) + end +end + +function run!(pass::NewPMLLVMPass, m::Module, tm::Union{Nothing,TargetMachine} = nothing, + aa_stack::AbstractVector{<:NewPMAliasAnalysis} = default_aa_pipeline(global_analyses=true)) + needs_globals_aa_recompute = any(aa_stack) do aa + isa(aa, GlobalsAA) + end + @dispose pic=StandardInstrumentationCallbacks() pb=PassBuilder(tm, pic) mpm=NewPMModulePassManager(pb) begin + # GlobalsAA needs to be computed before it can be used + if needs_globals_aa_recompute + add!(mpm, RecomputeGlobalsAAPass()) + end + if is_module_pass(typeof(pass)) + add!(mpm, pb, pass) + elseif is_cgscc_pass(typeof(pass)) + add!(mpm, NewPMCGSCCPassManager) do cpm + add!(cpm, pass) + end + elseif is_function_pass(typeof(pass)) + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, pass) + end + else + @assert is_loop_pass(typeof(pass)) + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, NewPMLoopPassManager) do lpm + add!(lpm, pass) + end + end + end + run!(mpm, m, tm, aa_stack) + end +end + +function run!(pass::NewPMLLVMPass, f::Function, tm::Union{Nothing,TargetMachine} = nothing, + aa_stack::AbstractVector{<:NewPMAliasAnalysis} = default_aa_pipeline()) + if any(aa->isa(aa, GlobalsAA), aa_stack) + throw(ArgumentError("GlobalsAA needs to be computed on a module, not a function!")) + end + @dispose pb=PassBuilder(tm) fpm=NewPMFunctionPassManager(pb) begin + if is_function_pass(typeof(pass)) + add!(fpm, pb, pass) + elseif is_loop_pass(typeof(pass)) + add!(fpm, NewPMLoopPassManager) do lpm + add!(lpm, pass) + end + else + throw(ArgumentError("Pass $pass is not a function or loop pass")) + end + run!(fpm, f, tm, aa_stack) end - add!(pm, pm.pb::PassBuilder, pass) end diff --git a/src/newpm/passmanager.jl b/src/newpm/passmanager.jl index 2413818a..098681b9 100644 --- a/src/newpm/passmanager.jl +++ b/src/newpm/passmanager.jl @@ -1,4 +1,5 @@ -export NewPMPassManager, NewPMModulePassManager, NewPMCGSCCPassManager, NewPMFunctionPassManager, NewPMLoopPassManager +export NewPMPassManager, NewPMModulePassManager, NewPMCGSCCPassManager, + NewPMFunctionPassManager, NewPMLoopPassManager export dispose, add! @@ -30,10 +31,14 @@ Base.unsafe_convert(::Type{API.LLVMCGSCCPassManagerRef}, pm::NewPMCGSCCPassManag Base.unsafe_convert(::Type{API.LLVMFunctionPassManagerRef}, pm::NewPMFunctionPassManager) = pm.ref Base.unsafe_convert(::Type{API.LLVMLoopPassManagerRef}, pm::NewPMLoopPassManager) = pm.ref -NewPMModulePassManager(pb) = NewPMModulePassManager(API.LLVMCreateNewPMModulePassManager(), [], pb) -NewPMCGSCCPassManager(pb) = NewPMCGSCCPassManager(API.LLVMCreateNewPMCGSCCPassManager(), [], pb) -NewPMFunctionPassManager(pb) = NewPMFunctionPassManager(API.LLVMCreateNewPMFunctionPassManager(), [], pb) -NewPMLoopPassManager(pb) = NewPMLoopPassManager(API.LLVMCreateNewPMLoopPassManager(), [], pb) +NewPMModulePassManager(pb) = + NewPMModulePassManager(API.LLVMCreateNewPMModulePassManager(), [], pb) +NewPMCGSCCPassManager(pb) = + NewPMCGSCCPassManager(API.LLVMCreateNewPMCGSCCPassManager(), [], pb) +NewPMFunctionPassManager(pb) = + NewPMFunctionPassManager(API.LLVMCreateNewPMFunctionPassManager(), [], pb) +NewPMLoopPassManager(pb) = + NewPMLoopPassManager(API.LLVMCreateNewPMLoopPassManager(), [], pb) dispose(pm::NewPMModulePassManager) = API.LLVMDisposeNewPMModulePassManager(pm) dispose(pm::NewPMCGSCCPassManager) = API.LLVMDisposeNewPMCGSCCPassManager(pm) @@ -107,8 +112,9 @@ function add!(pm::NewPMCGSCCPassManager, pm2::NewPMFunctionPassManager) API.LLVMCGPMAddFPM(pm, pm2) append!(pm.roots, pm2.roots) end -function add!(pm::NewPMFunctionPassManager, pm2::NewPMLoopPassManager) - API.LLVMFPMAddLPM(pm, pm2) +function add!(pm::NewPMFunctionPassManager, pm2::NewPMLoopPassManager, + UseMemorySSA::Core.Bool=false) + API.LLVMFPMAddLPM(pm, pm2, UseMemorySSA) append!(pm.roots, pm2.roots) end @@ -123,7 +129,7 @@ function add!(f::Core.Function, pm::NewPMModulePassManager, ::Type{NewPMModulePa end function add!(f::Core.Function, pm::NewPMCGSCCPassManager, ::Type{NewPMCGSCCPassManager}) - pm2 = NewPMCGSCCPassManager(om.pb) + pm2 = NewPMCGSCCPassManager(pm.pb) try f(pm2) add!(pm, pm2) @@ -182,16 +188,18 @@ function add!(f::Core.Function, pm::NewPMCGSCCPassManager, ::Type{NewPMFunctionP end end -function add!(f::Core.Function, pm::NewPMFunctionPassManager, ::Type{NewPMLoopPassManager}) +function add!(f::Core.Function, pm::NewPMFunctionPassManager, ::Type{NewPMLoopPassManager}, UseMemorySSA::Core.Bool=false) pm2 = NewPMLoopPassManager(pm.pb) try f(pm2) - add!(pm, pm2) + add!(pm, pm2, UseMemorySSA) finally dispose(pm2) end end -run!(pm::NewPMModulePassManager, m::Module, am::ModuleAnalysisManager) = PreservedAnalyses(API.LLVMRunNewPMModulePassManager(pm, m, am)) +run!(pm::NewPMModulePassManager, m::Module, am::ModuleAnalysisManager) = + PreservedAnalyses(API.LLVMRunNewPMModulePassManager(pm, m, am)) -run!(pm::NewPMFunctionPassManager, f::Function, am::FunctionAnalysisManager) = PreservedAnalyses(API.LLVMRunNewPMFunctionPassManager(pm, f, am)) +run!(pm::NewPMFunctionPassManager, f::Function, am::FunctionAnalysisManager) = + PreservedAnalyses(API.LLVMRunNewPMFunctionPassManager(pm, f, am)) diff --git a/test/newpm_tests.jl b/test/newpm_tests.jl index e6b42dcc..d3ddb375 100644 --- a/test/newpm_tests.jl +++ b/test/newpm_tests.jl @@ -1,3 +1,4 @@ + @testitem "newpm" begin using InteractiveUtils # for subtypes @@ -129,13 +130,19 @@ end # testset "newpm analysis registration" host_triple = triple() host_t = Target(triple=host_triple) -@dispose tm=TargetMachine(host_t, host_triple) pic=StandardInstrumentationCallbacks() pb=PassBuilder(tm, pic) begin +@dispose tm=TargetMachine(host_t, host_triple) pb=PassBuilder(tm) begin analysis_managers() do lam, fam, cam, mam register!(pb, lam, fam, cam, mam) NewPMModulePassManager(pb) do mpm for pass in filter(is_module_pass, subtypes(NewPMLLVMPass)) - add!(mpm, pass()) + try + add!(mpm, pass()) + @test "Successfully added $(pass)!" != "" + catch err + @test "Failed to add $(pass)!" == "" + @error err + end end end @test "Successfully added all module passes!" != "" @@ -143,7 +150,13 @@ host_t = Target(triple=host_triple) NewPMModulePassManager(pb) do mpm add!(mpm, NewPMCGSCCPassManager) do cgpm for pass in filter(is_cgscc_pass, subtypes(NewPMLLVMPass)) - add!(cgpm, pass()) + try + add!(cgpm, pass()) + @test "Successfully added $(pass)!" != "" + catch err + @test "Failed to add $(pass)!" == "" + @error err + end end end end @@ -153,7 +166,13 @@ host_t = Target(triple=host_triple) NewPMModulePassManager(pb) do mpm add!(mpm, NewPMFunctionPassManager) do fpm for pass in filter(is_function_pass, subtypes(NewPMLLVMPass)) - add!(fpm, pass()) + try + add!(fpm, pass()) + @test "Successfully added $(pass)!" != "" + catch err + @test "Failed to add $(pass)!" == "" + @error err + end end end end @@ -164,13 +183,49 @@ host_t = Target(triple=host_triple) add!(mpm, NewPMFunctionPassManager) do fpm add!(fpm, NewPMLoopPassManager) do lpm for pass in filter(is_loop_pass, subtypes(NewPMLLVMPass)) - add!(lpm, pass()) + try + add!(lpm, pass()) + @test "Successfully added $(pass)!" != "" + catch err + @test "Failed to add $(pass)!" == "" + @error err + end end end end end @test "Successfully added all loop passes!" != "" + + NewPMModulePassManager(pb) do mpm + add!(mpm, NewPMModulePassManager) do mpm2 + add!(mpm2, NewPMCGSCCPassManager) do cgpm + add!(cgpm, NewPMCGSCCPassManager) do cgpm2 + add!(cgpm2, NewPMFunctionPassManager) do fpm + add!(fpm, NewPMFunctionPassManager) do fpm2 + add!(fpm2, NewPMLoopPassManager) do lpm + add!(lpm, NewPMLoopPassManager) do lpm2 + @test_throws LLVMException parse!(pb, lpm2, "nonexistent") + end + end + @test_throws LLVMException parse!(pb, fpm2, "nonexistent") + end + end + @test_throws LLVMException parse!(pb, cgpm2, "nonexistent") + end + end + @test_throws LLVMException parse!(pb, mpm2, "nonexistent") + end + end + + @test "Successfully added nested pass managers!" != "" + + # As of LLVM 15 this count is 279, may change with each version based on LLVM's whims + if VERSION >= v"1.10.0-DEV.1622" + @test length(subtypes(NewPMLLVMPass)) == 279 + else + @test length(subtypes(NewPMLLVMPass)) == 262 + end end end @@ -181,7 +236,7 @@ end # testset "newpm passes" host_triple = triple() host_t = Target(triple=host_triple) -@dispose tm=TargetMachine(host_t, host_triple) pic=StandardInstrumentationCallbacks() pb=PassBuilder(tm, pic) begin +@dispose tm=TargetMachine(host_t, host_triple) pb=PassBuilder(tm) begin analysis_managers() do lam, fam, cam, mam register!(pb, lam, fam, cam, mam) @@ -203,11 +258,11 @@ host_t = Target(triple=host_triple) @test "Successfully added custom module and function passes!" != "" @dispose ctx=Context() builder=IRBuilder() mod=LLVM.Module("test") begin - pa = run!(mpm, mod, mam) - @test observed_modules == 1 - @test observed_functions == 0 - @test are_all_preserved(pa) - + @dispose pa=run!(mpm, mod, mam) begin + @test observed_modules == 1 + @test observed_functions == 0 + @test are_all_preserved(pa) + end ft = LLVM.FunctionType(LLVM.VoidType()) fn = LLVM.Function(mod, "SomeFunction", ft) @@ -217,15 +272,374 @@ host_t = Target(triple=host_triple) ret!(builder) - pa = run!(mpm, mod, mam) - @test observed_modules == 2 - @test observed_functions == 1 - @test are_all_preserved(pa) + @dispose pa=run!(mpm, mod, mam) begin + @test observed_modules == 2 + @test observed_functions == 1 + @test are_all_preserved(pa) + end end end end end -end # testset "newpm passes" +function fake_custom_legacy_pass(counter::Ref{Int}) + return ir -> begin + counter[] += 1 + return false + end +end + +@dispose tm=TargetMachine(host_t, host_triple) pb=PassBuilder(tm) begin + + observed_modules = Ref{Int}(0) + observed_functions = Ref{Int}(0) + @dispose mpm=NewPMModulePassManager(pb) begin + add!(legacy2newpm(fake_custom_legacy_pass(observed_modules)), mpm) + add!(mpm, NewPMFunctionPassManager) do fpm + add!(legacy2newpm(fake_custom_legacy_pass(observed_functions)), fpm) + end + + @dispose ctx=Context() builder=IRBuilder() mod=LLVM.Module("test") begin + run!(mpm, mod) + + @test observed_modules[] == 1 + @test observed_functions[] == 0 + + ft = LLVM.FunctionType(LLVM.VoidType()) + fn = LLVM.Function(mod, "SomeFunction", ft) + + entry = BasicBlock(fn, "entry") + position!(builder, entry) + + ret!(builder) + + run!(mpm, mod) + @test observed_modules[] == 2 + @test observed_functions[] == 1 + end + end +end + +end # testset "newpm custom passes" + +@testset "newpm analyses" begin + +host_triple = triple() +host_t = Target(triple=host_triple) + +@dispose tm=TargetMachine(host_t, host_triple) pb=PassBuilder(tm) begin + analysis_managers() do lam, fam, cam, mam + @test add!(fam, AAManager) do aam + # Do nothing + end + @test !add!(fam, AAManager) do aam + # Shouldn't run + @test "Ran an AA manager callback when another AA manager was already registered" + end + register!(pb, lam, fam, cam, mam) + end + @test "Registered an empty AA manager!" != "" + + analysis_managers() do lam, fam, cam, mam + add!(fam, AAManager) do aam + add!(aam, BasicAA()) + end + register!(pb, lam, fam, cam, mam) + end + @test "Registered a single alias analysis pass!" != "" + + analysis_managers() do lam, fam, cam, mam + add!(fam, AAManager) do aam + add!(aam, BasicAA()) + add!(aam, CFLAndersAA()) + add!(aam, CFLSteensAA()) + add!(aam, ObjCARCAA()) + add!(aam, ScopedNoAliasAA()) + add!(aam, TypeBasedAA()) + add!(aam, GlobalsAA()) + end + register!(pb, lam, fam, cam, mam) + end + @test "Registered all alias analysis passes!" != "" + + analysis_managers() do lam, fam, cam, mam + add!(fam, TargetIRAnalysis(tm)) + add!(fam, TargetLibraryAnalysis(host_triple)) + register!(pb, lam, fam, cam, mam) + end + @test "Registered target analyses!" != "" + + aa_stack = [BasicAA(), ScopedNoAliasAA(), TypeBasedAA()] + analysis_managers(nothing, tm, aa_stack) do lam, fam, cam, mam + register!(pb, lam, fam, cam, mam) + end + @test "Implicitly registered alias analyses and target analyses!" != "" +end + +end # testset "newpm analyses" + +@testset "newpm convenience functions" begin + +@dispose ctx=Context() builder=IRBuilder() mod=LLVM.Module("test") begin + ft = LLVM.FunctionType(LLVM.VoidType()) + fn = LLVM.Function(mod, "SomeFunction", ft) + + entry = BasicBlock(fn, "entry") + position!(builder, entry) + + ret!(builder) + + @test isnothing(run!(ForceFunctionAttrsPass(), mod)) + + @test "Successfully ran with just module pass and module!" != "" + + @test isnothing(run!(ArgumentPromotionPass(), mod)) + + @test "Successfully ran with just cgscc pass and module!" != "" + + @test isnothing(run!(SimplifyCFGPass(), mod)) + + @test "Successfully ran with just function pass and module!" != "" + + @test isnothing(run!(LICMPass(), mod)) + + @test "Successfully ran with just loop pass and module!" != "" + + @test isnothing(run!(SimplifyCFGPass(), fn)) + + @test "Successfully ran with just function pass and function!" != "" + + @test isnothing(run!(LICMPass(), fn)) + + @test "Successfully ran with just loop pass and function!" != "" + + host_triple = triple() + host_t = Target(triple=host_triple) + + @dispose tm=TargetMachine(host_t, host_triple) begin + @test isnothing(run!(SimplifyCFGPass(), fn, tm)) + end + + @test "Successfully forwarded target machine and alias analyses!" != "" +end + +end # testset "newpm convenience functions" + +@testset "newpm error checking" begin +@dispose mpm=NewPMModulePassManager() begin + @test_throws ArgumentError add!(mpm, RecomputeGlobalsAAPass()) +end + +@dispose cpm=NewPMCGSCCPassManager() begin + @test_throws ArgumentError add!(cpm, ArgumentPromotionPass()) +end + +@dispose fpm=NewPMFunctionPassManager() begin + @test_throws ArgumentError add!(fpm, SimplifyCFGPass()) +end + +@dispose lpm=NewPMLoopPassManager() begin + @test_throws ArgumentError add!(lpm, LICMPass()) +end + +@dispose pb=PassBuilder() begin + @dispose mpm=NewPMModulePassManager(pb) begin + @test_throws ArgumentError add!(mpm, SimplifyCFGPass()) + end + + @dispose cpm=NewPMCGSCCPassManager(pb) begin + @test_throws ArgumentError add!(cpm, SimplifyCFGPass()) + end + + @dispose fpm=NewPMFunctionPassManager(pb) begin + @test_throws ArgumentError add!(fpm, RecomputeGlobalsAAPass()) + end + + @dispose lpm=NewPMLoopPassManager(pb) begin + @test_throws ArgumentError add!(lpm, RecomputeGlobalsAAPass()) + end +end + +@dispose ctx=Context() builder=IRBuilder() mod=LLVM.Module("test") begin + ft = LLVM.FunctionType(LLVM.VoidType()) + fn = LLVM.Function(mod, "SomeFunction", ft) + + entry = BasicBlock(fn, "entry") + position!(builder, entry) + + ret!(builder) + + host_triple = triple() + host_t = Target(triple=host_triple) + + @dispose tm=TargetMachine(host_t, host_triple) begin + @test isnothing(run!(SimplifyCFGPass(), mod, tm, [GlobalsAA()])) + @test_throws ArgumentError run!(SimplifyCFGPass(), fn, tm, [GlobalsAA()]) + end +end + +end # testset "newpm error checking" + +if VERSION >= v"1.10.0-DEV.1622" + +using LLVM.Interop + +# Copy of the julia pipeline from julia/src/pipeline.cpp +@testset "newpm julia pipeline" begin +host_triple = triple() +host_t = Target(triple=host_triple) +@dispose tm=TargetMachine(host_t, host_triple) pb=PassBuilder(tm) begin + basicSimplifyCFGOptions = + SimplifyCFGPassOptions(; forward_switch_cond_to_phi=true, + convert_switch_range_to_icmp=true, + convert_switch_to_lookup_table=true) + aggressiveSimplifyCFGOptions = + SimplifyCFGPassOptions(; forward_switch_cond_to_phi=true, + convert_switch_range_to_icmp=true, + convert_switch_to_lookup_table=true, + hoist_common_insts=true) + NewPMModulePassManager(pb) do mpm + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, GCInvariantVerifierPass()) + end + add!(mpm, VerifierPass()) + add!(mpm, ForceFunctionAttrsPass()) + add!(mpm, Annotation2MetadataPass()) + add!(mpm, ConstantMergePass()) + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, LowerExpectIntrinsicPass()) + add!(fpm, PropagateJuliaAddrspacesPass()) + add!(fpm, SimplifyCFGPass(basicSimplifyCFGOptions)) + add!(fpm, DCEPass()) + add!(fpm, SROAPass()) + end + add!(mpm, AlwaysInlinerPass()) + add!(mpm, NewPMCGSCCPassManager) do cgpm + add!(cgpm, NewPMFunctionPassManager) do fpm + add!(fpm, AllocOptPass()) + add!(fpm, Float2IntPass()) + add!(fpm, LowerConstantIntrinsicsPass()) + end + end + add!(mpm, CPUFeaturesPass()) + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, SROAPass()) + add!(fpm, InstCombinePass()) + add!(fpm, JumpThreadingPass()) + add!(fpm, CorrelatedValuePropagationPass()) + add!(fpm, ReassociatePass()) + add!(fpm, EarlyCSEPass()) + add!(fpm, AllocOptPass()) + end + add!(mpm, LowerSIMDLoopPass()) + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, NewPMLoopPassManager) do lpm + add!(lpm, LoopRotatePass()) + end + add!(fpm, NewPMLoopPassManager, #=UseMemorySSA=#true) do lpm + add!(lpm, LICMPass()) + add!(lpm, JuliaLICMPass()) + add!(lpm, SimpleLoopUnswitchPass()) + add!(lpm, LICMPass()) + add!(lpm, JuliaLICMPass()) + end + add!(fpm, IRCEPass()) + add!(fpm, NewPMLoopPassManager) do lpm + add!(lpm, LoopInstSimplifyPass()) + add!(lpm, LoopIdiomRecognizePass()) + add!(lpm, IndVarSimplifyPass()) + add!(lpm, LoopDeletionPass()) + add!(lpm, LoopFullUnrollPass()) + end + add!(fpm, SROAPass()) + add!(fpm, InstSimplifyPass()) + add!(fpm, GVNPass()) + add!(fpm, MemCpyOptPass()) + add!(fpm, SCCPPass()) + add!(fpm, CorrelatedValuePropagationPass()) + add!(fpm, DCEPass()) + add!(fpm, IRCEPass()) + add!(fpm, InstCombinePass()) + add!(fpm, JumpThreadingPass()) + add!(fpm, GVNPass()) + add!(fpm, DSEPass()) + add!(fpm, SimplifyCFGPass(aggressiveSimplifyCFGOptions)) + add!(fpm, AllocOptPass()) + add!(fpm, NewPMLoopPassManager) do lpm + add!(lpm, LoopDeletionPass()) + add!(lpm, LoopInstSimplifyPass()) + end + add!(fpm, LoopDistributePass()) + add!(fpm, InjectTLIMappings()) + add!(fpm, LoopVectorizePass()) + add!(fpm, LoopLoadEliminationPass()) + add!(fpm, InstCombinePass()) + add!(fpm, SimplifyCFGPass(aggressiveSimplifyCFGOptions)) + add!(fpm, SLPVectorizerPass()) + add!(fpm, VectorCombinePass()) + add!(fpm, ADCEPass()) + add!(fpm, LoopUnrollPass()) + add!(fpm, WarnMissedTransformationsPass()) + end + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, LowerExcHandlersPass()) + add!(fpm, GCInvariantVerifierPass()) + end + add!(mpm, RemoveNIPass()) + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, LateLowerGCPass()) + if VERSION >= v"1.11.0-DEV.208" + add!(fpm, FinalLowerGCPass()) + end + end + if VERSION < v"1.11.0-DEV.208" + add!(mpm, FinalLowerGCPass()) + end + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, GVNPass()) + add!(fpm, SCCPPass()) + add!(fpm, DCEPass()) + end + add!(mpm, LowerPTLSPass()) + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, InstCombinePass()) + add!(fpm, SimplifyCFGPass(aggressiveSimplifyCFGOptions)) + end + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, CombineMulAddPass()) + add!(fpm, DivRemPairsPass()) + end + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, AnnotationRemarksPass()) + end + add!(mpm, NewPMFunctionPassManager) do fpm + add!(fpm, DemoteFloat16Pass()) + add!(fpm, GVNPass()) + end + + @test "Successfully created julia pipeline!" != "" + + @dispose ctx=Context() builder=IRBuilder() mod=LLVM.Module("test") begin + ft = LLVM.FunctionType(LLVM.VoidType()) + fn = LLVM.Function(mod, "SomeFunction", ft) + + entry = BasicBlock(fn, "entry") + position!(builder, entry) + + ret!(builder) + + run!(mpm, mod, tm) + end + end +end + +@test "Successfully ran julia pipeline!" != "" + +@test string(JuliaPipelinePass(; opt_level=2)) == + "julia" + +end # testset "newpm julia pipeline" + +end # VERSION >= v"1.10.0-DEV.1622" end