-
Notifications
You must be signed in to change notification settings - Fork 25
Fully upstream lowering pipeline #452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
2cf9724
a63e139
fc8ed5e
c7dd516
3f594a8
9c6369c
f7433f5
1cf0010
ec2b19d
7e4c6c8
8b34f65
8038c35
2a4c7fd
1bfa8d8
b3b09f5
42839d1
254cb7a
f21d597
413aa85
6173205
dd23422
0da8d14
3cc0aed
046b578
be6f25e
f7f458c
16fbe83
a8f9eeb
9c88480
0051194
3b40efd
cfe5a09
e6218cd
0735065
ae60dbb
41d2856
7855c4c
7d7af5a
e466b9d
225f4bf
8db1648
35e9ed6
d8d3fac
342601e
d8dbefc
4f2bce4
29c68c6
460206e
18ace68
b8f1ba1
57b6a2f
2b77f89
d714cf7
c3edecc
c8135b0
debc49e
3fcf325
67bf7ed
ab44800
3b414ab
5a491c3
4e6b923
43453f2
ab76725
aada62f
15aa357
3cbe616
435105f
24710f4
09a304c
2dcd0de
3564e79
85983d3
cb29e98
ce34549
e3ba1a5
15f9bd8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| # Copyright 2025 The IREE Authors | ||
| # Licensed under the Apache License v2.0 with LLVM Exceptions. | ||
| # See https://llvm.org/LICENSE.txt for license information. | ||
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
|
||
| """ | ||
| Tests for the ExecutionEngine wrapper with weak reference caching. | ||
| """ | ||
|
|
||
| import gc | ||
| import os | ||
| import pytest | ||
| import weakref | ||
|
|
||
| from wave_lang.kernel.wave.execution_engine import ( | ||
| clear_engine_cache, | ||
| get_execution_engine, | ||
| is_engine_cached, | ||
| is_execution_engine_available, | ||
| ) | ||
|
|
||
| pytestmark = pytest.mark.skipif( | ||
| not is_execution_engine_available(), | ||
| reason="ExecutionEngine not available (C++ extension not built)", | ||
| ) | ||
|
|
||
|
|
||
| ENV_VARS = [ | ||
| "WAVE_ENABLE_OBJECT_CACHE", | ||
| "WAVE_ENABLE_GDB_LISTENER", | ||
| "WAVE_ENABLE_PERF_LISTENER", | ||
| ] | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def clean_env(): | ||
| """Fixture to clean cache and environment variables before/after each test.""" | ||
| clear_engine_cache() | ||
|
|
||
| # Save original env vars | ||
| orig_env = {} | ||
| for key in ENV_VARS: | ||
| orig_env[key] = os.environ.get(key) | ||
| if key in os.environ: | ||
| del os.environ[key] | ||
|
|
||
| yield | ||
|
|
||
| # Restore original env vars | ||
| for key, value in orig_env.items(): | ||
| if value is not None: | ||
| os.environ[key] = value | ||
| elif key in os.environ: | ||
| del os.environ[key] | ||
|
|
||
| clear_engine_cache() | ||
| gc.collect() | ||
|
|
||
|
|
||
| def test_basic_creation(clean_env): | ||
| """Test basic creation of execution engine.""" | ||
| engine = get_execution_engine() | ||
| assert engine is not None | ||
| assert is_engine_cached() | ||
|
|
||
|
|
||
| def test_cache_returns_same_instance(clean_env): | ||
| """Test that cache returns the same instance.""" | ||
| engine1 = get_execution_engine() | ||
| engine2 = get_execution_engine() | ||
|
|
||
| # Should be the exact same object | ||
| assert engine1 is engine2 | ||
|
|
||
|
|
||
| def test_weak_reference_cleanup(clean_env): | ||
| """Test that engine is cleaned up when references are released.""" | ||
| # Create engine and get weak reference | ||
| engine = get_execution_engine() | ||
| weak_ref = weakref.ref(engine) | ||
|
|
||
| # Verify it's cached | ||
| assert is_engine_cached() | ||
|
|
||
| # Delete strong reference | ||
| del engine | ||
| gc.collect() | ||
|
|
||
| # Weak reference should be dead | ||
| assert weak_ref() is None | ||
|
|
||
| # Cache should report no engine | ||
| assert not is_engine_cached() | ||
|
|
||
|
|
||
| def test_clear_cache(clean_env): | ||
| """Test that clear_cache removes cached engine.""" | ||
| engine = get_execution_engine() | ||
| assert is_engine_cached() | ||
|
|
||
| # Clear cache | ||
| clear_engine_cache() | ||
|
|
||
| # Cache should be empty | ||
| assert not is_engine_cached() | ||
|
|
||
| # Engine should still be alive (we have strong reference) | ||
| assert engine is not None | ||
|
|
||
|
|
||
| def test_env_var_object_cache(clean_env): | ||
| """Test WAVE_ENABLE_OBJECT_CACHE environment variable.""" | ||
| os.environ["WAVE_ENABLE_OBJECT_CACHE"] = "1" | ||
|
|
||
| engine = get_execution_engine() | ||
| assert engine is not None | ||
| # We can't directly test if object cache is enabled without | ||
| # accessing internal state, but we verify the engine was created | ||
|
|
||
|
|
||
| def test_env_var_gdb_listener(clean_env): | ||
| """Test WAVE_ENABLE_GDB_LISTENER environment variable.""" | ||
| os.environ["WAVE_ENABLE_GDB_LISTENER"] = "1" | ||
|
|
||
| engine = get_execution_engine() | ||
| assert engine is not None | ||
|
|
||
|
|
||
| def test_env_var_perf_listener(clean_env): | ||
| """Test WAVE_ENABLE_PERF_LISTENER environment variable.""" | ||
| os.environ["WAVE_ENABLE_PERF_LISTENER"] = "1" | ||
|
|
||
| engine = get_execution_engine() | ||
| assert engine is not None | ||
|
|
||
|
|
||
| def test_all_env_vars(clean_env): | ||
| """Test all environment variables together.""" | ||
| os.environ["WAVE_ENABLE_OBJECT_CACHE"] = "1" | ||
| os.environ["WAVE_ENABLE_GDB_LISTENER"] = "1" | ||
| os.environ["WAVE_ENABLE_PERF_LISTENER"] = "1" | ||
|
|
||
| engine = get_execution_engine() | ||
| assert engine is not None | ||
| assert is_engine_cached() | ||
|
|
||
|
|
||
| def test_multiple_references(clean_env): | ||
| """Test that multiple references to the same engine work correctly.""" | ||
| engine1 = get_execution_engine() | ||
| engine2 = get_execution_engine() | ||
| engine3 = get_execution_engine() | ||
|
|
||
| # All should be the same object | ||
| assert engine1 is engine2 | ||
| assert engine2 is engine3 | ||
|
|
||
|
|
||
| def test_engine_interface(clean_env): | ||
| """Test that the engine provides the correct interface.""" | ||
| engine = get_execution_engine() | ||
|
|
||
| # Check that required methods exist | ||
| assert hasattr(engine, "load_module") | ||
| assert hasattr(engine, "release_module") | ||
| assert hasattr(engine, "lookup") | ||
| assert hasattr(engine, "dump_to_object_file") | ||
|
|
||
| # Check that methods are callable | ||
| assert callable(engine.load_module) | ||
| assert callable(engine.release_module) | ||
| assert callable(engine.lookup) | ||
| assert callable(engine.dump_to_object_file) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| pytest.main([__file__, "-v"]) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,11 @@ set(LIBS | |
|
|
||
| MLIRWaterTestTransforms | ||
| MLIRWaterTestDialect | ||
|
|
||
| MLIRRegisterAllDialects | ||
| MLIRRegisterAllExtensions | ||
| MLIRRegisterAllPasses | ||
|
Comment on lines
+16
to
+18
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't. Just pick what you need. Otherwise this significantly increases build times and distribution sizes, and is near impossible to undo. |
||
| MLIRToLLVMIRTranslationRegistration | ||
| ) | ||
|
|
||
| add_llvm_executable(water-opt | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,7 +20,9 @@ | |
| #include "mlir/Dialect/Vector/IR/VectorOps.h" | ||
| #include "mlir/IR/MLIRContext.h" | ||
| #include "mlir/InitAllDialects.h" | ||
| #include "mlir/InitAllExtensions.h" | ||
| #include "mlir/InitAllPasses.h" | ||
| #include "mlir/Target/LLVMIR/Dialect/All.h" | ||
| #include "mlir/Tools/mlir-opt/MlirOptMain.h" | ||
| #include "mlir/Transforms/Passes.h" | ||
|
|
||
|
|
@@ -40,20 +42,15 @@ int main(int argc, char **argv) { | |
| mlir::water::registerPasses(); | ||
| mlir::water::test::registerAllPasses(); | ||
| wave::registerPasses(); | ||
| mlir::arith::registerArithIntRangeOptsPass(); | ||
| mlir::registerCanonicalizerPass(); | ||
| mlir::registerCSEPass(); | ||
| mlir::registerLoopInvariantCodeMotionPass(); | ||
| mlir::registerLowerAffinePass(); | ||
|
|
||
| mlir::registerAllPasses(); | ||
| mlir::DialectRegistry registry; | ||
| registry.insert<mlir::affine::AffineDialect, mlir::amdgpu::AMDGPUDialect, | ||
| mlir::arith::ArithDialect, mlir::cf::ControlFlowDialect, | ||
| mlir::func::FuncDialect, mlir::gpu::GPUDialect, | ||
| mlir::LLVM::LLVMDialect, mlir::ROCDL::ROCDLDialect, | ||
| mlir::memref::MemRefDialect, mlir::scf::SCFDialect, | ||
| mlir::vector::VectorDialect, wave::WaveDialect>(); | ||
| mlir::registerAllDialects(registry); | ||
| mlir::registerAllExtensions(registry); | ||
|
Comment on lines
+48
to
+49
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't. |
||
|
|
||
| mlir::registerAllGPUToLLVMIRTranslations(registry); | ||
|
|
||
| registry.insert<wave::WaveDialect>(); | ||
| mlir::water::test::registerWaterTestDialect(registry); | ||
|
|
||
| return mlir::asMainReturnCode( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So Wave EE is under
BUILD_WATERflag. Are we moving towards rebranding the MLIR layer of Wave Water? If so, let's update the documentation.