Skip to content

CodeRabbit Generated Unit Tests: Generate 6 unit test files#1499

Draft
coderabbitai[bot] wants to merge 2 commits intomainfrom
coderabbitai/utg/4e9f745
Draft

CodeRabbit Generated Unit Tests: Generate 6 unit test files#1499
coderabbitai[bot] wants to merge 2 commits intomainfrom
coderabbitai/utg/4e9f745

Conversation

@coderabbitai
Copy link
Contributor

@coderabbitai coderabbitai bot commented Feb 5, 2026

Unit test generation was requested by @taminob.

The following files were modified:

  • TEST_SUMMARY.md
  • mlir/unittests/decomposition/test_basis_decomposer.cpp
  • mlir/unittests/decomposition/test_euler_decomposition.cpp
  • mlir/unittests/decomposition/test_helpers.cpp
  • mlir/unittests/decomposition/test_unitary_matrices.cpp
  • mlir/unittests/decomposition/test_weyl_decomposition.cpp

@github-actions
Copy link
Contributor

github-actions bot commented Feb 5, 2026

Cpp-Linter Report ⚠️

Some files did not pass the configured checks!

clang-tidy (v21.1.8) reports: 28 concern(s)
  • mlir/unittests/decomposition/test_basis_decomposer.cpp:11:10: error: [clang-diagnostic-error]

    'ir/operations/OpType.hpp' file not found

       11 | #include "ir/operations/OpType.hpp"
          |          ^~~~~~~~~~~~~~~~~~~~~~~~~~
  • mlir/unittests/decomposition/test_basis_decomposer.cpp:27:1: warning: [misc-include-cleaner]

    included header SmallVector.h is not used directly

       27 | #include <llvm/ADT/SmallVector.h>
          | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       28 | #include <optional>
  • mlir/unittests/decomposition/test_basis_decomposer.cpp:29:1: warning: [misc-include-cleaner]

    included header tuple is not used directly

       29 | #include <tuple>
          | ^~~~~~~~~~~~~~~~
       30 | 
  • mlir/unittests/decomposition/test_basis_decomposer.cpp:35:25: warning: [llvm-prefer-static-over-anonymous-namespace]

    function 'randomUnitaryMatrix' is declared in an anonymous namespace; prefer using 'static' for restricting visibility

       35 | [[nodiscard]] matrix4x4 randomUnitaryMatrix() {
          |                         ^
  • mlir/unittests/decomposition/test_basis_decomposer.cpp:50:25: warning: [llvm-prefer-static-over-anonymous-namespace]

    function 'canonicalGate' is declared in an anonymous namespace; prefer using 'static' for restricting visibility

       50 | [[nodiscard]] matrix4x4 canonicalGate(fp a, fp b, fp c) {
          |                         ^
  • mlir/unittests/decomposition/test_basis_decomposer.cpp:63:8: warning: [readability-identifier-naming]

    invalid case style for method 'SetUp'

       63 |   void SetUp() override {
          |        ^~~~~
          |        setUp
  • mlir/unittests/decomposition/test_basis_decomposer.cpp:98:10: warning: [readability-implicit-bool-conversion]

    implicit conversion 'const char *' -> 'bool'

       98 |       << "RESULT:\n"
          |          ^~~~~~~~~~~
          |          true
  • mlir/unittests/decomposition/test_basis_decomposer.cpp:113:10: warning: [readability-implicit-bool-conversion]

    implicit conversion 'const char *' -> 'bool'

      113 |       << "RESULT:\n"
          |          ^~~~~~~~~~~
          |          true
  • mlir/unittests/decomposition/test_basis_decomposer.cpp:139:12: warning: [readability-implicit-bool-conversion]

    implicit conversion 'const char *' -> 'bool'

      139 |         << "ORIGINAL:\n"
          |            ^~~~~~~~~~~~~
          |            true
  • mlir/unittests/decomposition/test_euler_decomposition.cpp:11:10: error: [clang-diagnostic-error]

    'mlir/Passes/Decomposition/EulerBasis.h' file not found

       11 | #include "mlir/Passes/Decomposition/EulerBasis.h"
          |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • mlir/unittests/decomposition/test_euler_decomposition.cpp:18:1: warning: [misc-include-cleaner]

    included header array is not used directly

       18 | #include <array>
          | ^~~~~~~~~~~~~~~~
       19 | #include <cassert>
  • mlir/unittests/decomposition/test_euler_decomposition.cpp:25:1: warning: [misc-include-cleaner]

    included header optional is not used directly

       25 | #include <optional>
          | ^~~~~~~~~~~~~~~~~~~
       26 | #include <tuple>
  • mlir/unittests/decomposition/test_euler_decomposition.cpp:26:1: warning: [misc-include-cleaner]

    included header tuple is not used directly

       26 | #include <tuple>
          | ^~~~~~~~~~~~~~~~
       27 | 
  • mlir/unittests/decomposition/test_euler_decomposition.cpp:32:25: warning: [llvm-prefer-static-over-anonymous-namespace]

    function 'randomUnitaryMatrix' is declared in an anonymous namespace; prefer using 'static' for restricting visibility

       32 | [[nodiscard]] matrix2x2 randomUnitaryMatrix() {
          |                         ^
  • mlir/unittests/decomposition/test_euler_decomposition.cpp:61:8: warning: [readability-identifier-naming]

    invalid case style for method 'SetUp'

       61 |   void SetUp() override {
          |        ^~~~~
          |        setUp
  • mlir/unittests/decomposition/test_euler_decomposition.cpp:77:10: warning: [readability-implicit-bool-conversion]

    implicit conversion 'const char *' -> 'bool'

       77 |       << "RESULT:\n"
          |          ^~~~~~~~~~~
          |          true
  • mlir/unittests/decomposition/test_euler_decomposition.cpp:95:12: warning: [readability-implicit-bool-conversion]

    implicit conversion 'const char *' -> 'bool'

       95 |         << "ORIGINAL:\n"
          |            ^~~~~~~~~~~~~
          |            true
  • mlir/unittests/decomposition/test_helpers.cpp:11:10: error: [clang-diagnostic-error]

    'mlir/Passes/Decomposition/Helpers.h' file not found

       11 | #include "mlir/Passes/Decomposition/Helpers.h"
          |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • mlir/unittests/decomposition/test_unitary_matrices.cpp:11:10: error: [clang-diagnostic-error]

    'mlir/Passes/Decomposition/Gate.h' file not found

       11 | #include "mlir/Passes/Decomposition/Gate.h"
          |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • mlir/unittests/decomposition/test_unitary_matrices.cpp:36:23: warning: [modernize-use-std-numbers]

    prefer 'std::numbers::sqrt2' to this formula

       36 |   fp sqrtHalf = 1.0 / std::sqrt(2.0);
          |                       ^~~~~~~~~~~~~~
          |                       std::numbers::sqrt2
  • mlir/unittests/decomposition/test_unitary_matrices.cpp:55:23: warning: [modernize-use-std-numbers]

    prefer 'std::numbers::sqrt2' to this formula

       55 |   fp sqrtHalf = 1.0 / std::sqrt(2.0);
          |                       ^~~~~~~~~~~~~~
          |                       std::numbers::sqrt2
  • mlir/unittests/decomposition/test_unitary_matrices.cpp:73:23: warning: [modernize-use-std-numbers]

    prefer 'std::numbers::sqrt2' to this formula

       73 |   fp sqrtHalf = 1.0 / std::sqrt(2.0);
          |                       ^~~~~~~~~~~~~~
          |                       std::numbers::sqrt2
  • mlir/unittests/decomposition/test_weyl_decomposition.cpp:11:10: error: [clang-diagnostic-error]

    'ir/operations/OpType.hpp' file not found

       11 | #include "ir/operations/OpType.hpp"
          |          ^~~~~~~~~~~~~~~~~~~~~~~~~~
  • mlir/unittests/decomposition/test_weyl_decomposition.cpp:28:25: warning: [llvm-prefer-static-over-anonymous-namespace]

    function 'randomUnitaryMatrix' is declared in an anonymous namespace; prefer using 'static' for restricting visibility

       28 | [[nodiscard]] matrix4x4 randomUnitaryMatrix() {
          |                         ^
  • mlir/unittests/decomposition/test_weyl_decomposition.cpp:43:25: warning: [llvm-prefer-static-over-anonymous-namespace]

    function 'canonicalGate' is declared in an anonymous namespace; prefer using 'static' for restricting visibility

       43 | [[nodiscard]] matrix4x4 canonicalGate(fp a, fp b, fp c) {
          |                         ^
  • mlir/unittests/decomposition/test_weyl_decomposition.cpp:84:10: warning: [readability-implicit-bool-conversion]

    implicit conversion 'const char *' -> 'bool'

       84 |       << "RESULT:\n"
          |          ^~~~~~~~~~~
          |          true
  • mlir/unittests/decomposition/test_weyl_decomposition.cpp:95:10: warning: [readability-implicit-bool-conversion]

    implicit conversion 'const char *' -> 'bool'

       95 |       << "RESULT:\n"
          |          ^~~~~~~~~~~
          |          true
  • mlir/unittests/decomposition/test_weyl_decomposition.cpp:109:12: warning: [readability-implicit-bool-conversion]

    implicit conversion 'const char *' -> 'bool'

      109 |         << "ORIGINAL:\n"
          |            ^~~~~~~~~~~~~
          |            true

Have any feedback or feature suggestions? Share it here.

@codecov
Copy link

codecov bot commented Feb 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@taminob
Copy link
Collaborator

taminob commented Feb 5, 2026

@coderabbitai how to test the decomposition in the context of the CompilerPipeline?

@taminob taminob marked this pull request as draft February 5, 2026 19:16
@coderabbitai
Copy link
Contributor Author

coderabbitai bot commented Feb 5, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@taminob, let me search for information about the CompilerPipeline and how decomposition is integrated to provide you with specific testing guidance.


🏁 Script executed:

#!/bin/bash

# Find CompilerPipeline implementation files
echo "=== Finding CompilerPipeline files ==="
fd -t f -e cpp -e hpp -e h CompilerPipeline

# Search for CompilerPipeline class definition
echo -e "\n=== CompilerPipeline class definition ==="
rg -n -C5 'class CompilerPipeline' --type=cpp --type=c

# Find existing CompilerPipeline tests
echo -e "\n=== Finding CompilerPipeline tests ==="
fd -t f -e cpp test.*pipeline

# Search for how decomposition is used in pipeline
echo -e "\n=== Decomposition usage in pipeline ==="
rg -n -C3 'decompos' --type=cpp --type=c -g '*pipeline*' -i

# Find integration test examples
echo -e "\n=== Finding integration tests ==="
fd -t f -e cpp -g '*test*' | grep -i integration | head -20

Length of output: 1285


#!/bin/bash

# Look at CompilerPipeline header to understand the interface
echo "=== CompilerPipeline header ==="
cat mlir/include/mlir/Compiler/CompilerPipeline.h

# Look at existing CompilerPipeline tests to understand patterns
echo -e "\n=== Existing CompilerPipeline test structure (first 200 lines) ==="
head -200 mlir/unittests/Compiler/test_compiler_pipeline.cpp

# Search for decomposition passes or transformations
echo -e "\n=== Searching for decomposition passes ==="
rg -n -C3 'decompos' --type=cpp -i -g '!test*' | head -50

# Find MLIR passes that might use decomposition
echo -e "\n=== Finding pass files ==="
fd -t f -e cpp -e h pass -i | head -20

Comment on lines +129 to +130
**Status**: Already has 76 comprehensive tests
**Action Taken**: Verified existing comprehensive coverage
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai how to test the application of the decomposition pass in the optimization stage of the compiler pipeline? That is currently not verified

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

@taminob, let me investigate the current test structure and decomposition pass implementation to provide guidance on testing the decomposition pass application.


🏁 Script executed:

#!/bin/bash

# Find compiler pipeline test file
echo "=== Compiler Pipeline Test File ==="
fd -t f "test_compiler_pipeline" --exec cat {}

echo -e "\n=== Decomposition Pass Files ==="
# Find decomposition pass implementation files
fd -t f -e cpp -e h "decompos" | head -20

echo -e "\n=== Sample Decomposition Pass Implementation ==="
# Look at decomposition pass implementation
rg -n "DecompositionPass\|decomposition.*Pass" -A 5 -B 2

echo -e "\n=== MLIR Pass Testing Patterns ==="
# Find how MLIR passes are tested in the codebase
rg -n "PassManager\|mlir::Pass" test/ -A 3 -B 1 | head -50

Length of output: 109060


@taminob, let me search for the decomposition pass implementation and how it's integrated into the optimization stage.


🏁 Script executed:

#!/bin/bash

# Find decomposition pass implementation and registration
echo "=== Decomposition Pass Implementation ==="
rg -n "class.*Decompos.*Pass" -A 10 -B 2

echo -e "\n=== Pass Registration ==="
rg -n "registerPass|createDecomposition" -A 3 -B 1

echo -e "\n=== Compiler Pipeline Optimization Stage ==="
rg -n "optimization|runOptimizationPasses" mlir/ -A 5 -B 2 | head -100

echo -e "\n=== Pass Manager Configuration ==="
fd -t f "CompilerPipeline" -e cpp -e h --exec rg -n "addPass|optimization" {} \; | head -100

echo -e "\n=== Look for gate decomposition in passes ==="
rg -n "decompose|Decompose" mlir/lib/Compiler/ -A 3 -B 1

Length of output: 7885


Let me look at the actual compiler pipeline implementation to understand the optimization stage better.


🏁 Script executed:

#!/bin/bash

# Find and examine CompilerPipeline implementation
echo "=== CompilerPipeline Header ==="
fd -t f "CompilerPipeline.h" --exec cat {}

echo -e "\n=== CompilerPipeline Implementation ==="
fd -t f "CompilerPipeline.cpp" --exec cat {}

echo -e "\n=== QCO Passes ==="
fd -t f -e h -e cpp . mlir/include/mlir/Dialect/QCO/Transforms/ mlir/lib/Dialect/QCO/Transforms/ --exec echo "File: {}" \; --exec head -50 {} \;

echo -e "\n=== Available Decomposition Functions ==="
rg -n "namespace decomposition|class.*Decomposer" mlir/include/ -A 5

Length of output: 12553


Let me search for QCO transformation passes to understand what's available:


🏁 Script executed:

#!/bin/bash

# Find QCO dialect transforms/passes
echo "=== Find QCO Transform Files ==="
fd -t f . mlir/lib/Dialect/QCO mlir/include/mlir/Dialect/QCO | grep -i transform

echo -e "\n=== Find Pass Definitions ==="
rg -n "def.*Pass|tablegen.*Pass" mlir/ -t td | head -50

echo -e "\n=== Look for gate decomposition utilities ==="
fd -t f "decomposition" mlir/ --exec basename {} \;

echo -e "\n=== Check existing QCO canonicalization patterns ==="
rg -n "getCanonicalizationPatterns|fold" mlir/lib/Dialect/QCO/ -A 3 -B 1 | head -100

echo -e "\n=== Look for basis translation or decomposition in QCO ==="
rg -n "basis|Basis|translate|decompose" mlir/lib/Dialect/QCO/ -A 2 | head -80

Length of output: 8772


Now I understand the issue! Let me check if there are any existing decomposition passes or if they need to be created:


🏁 Script executed:

#!/bin/bash

# Look for any pass infrastructure or decomposition utilities
echo "=== Search for Pass declarations ==="
fd -t f -e h . mlir/include/ | xargs rg -l "Pass.h|Passes.h" | head -20

echo -e "\n=== Check for existing transformation passes ==="
rg -n "create.*Pass\(\)" mlir/include/ -A 2 | head -80

echo -e "\n=== Look at the conversion passes to see pattern ==="
cat mlir/include/mlir/Conversion/QCToQCO/QCToQCO.h

echo -e "\n=== Check decomposition library headers ==="
fd -t f -e h "decomposition" mlir/include/

echo -e "\n=== Look for basis translator ==="
rg -n "BasisTranslator|translateToBasis" mlir/ -A 3 | head -50

Length of output: 854


Perfect! Now I have a complete understanding of the situation. Let me provide you with a comprehensive answer on how to test the decomposition pass in the optimization stage.

@taminob, great catch! You're absolutely right that the decomposition pass application is not currently verified. Here's the situation and how to fix it:

Current State

Looking at the code, I found that:

  1. The optimization stage is not yet implemented - Line 163 in CompilerPipeline.cpp has a TODO:

    // Stage 5: Optimization passes
    // TODO: Add optimization passes
    addCleanupPasses(pm);
  2. Decomposition logic exists but isn't integrated - You have decomposition tests (test_basis_decomposer.cpp, test_euler_decomposition.cpp, test_weyl_decomposition.cpp) that test the mathematical decomposition algorithms, but there's no MLIR pass that applies these during compilation.

  3. No pass tests - The 76 tests in test_compiler_pipeline.cpp verify IR transformations but don't test decomposition because the pass doesn't exist yet.

How to Test Decomposition Pass Application

You need to:

1. Create a Decomposition Pass

Create a new pass following the pattern of your conversion passes:

// mlir/include/mlir/Dialect/QCO/Transforms/Passes.h
`#pragma` once

`#include` <mlir/Pass/Pass.h>

namespace mlir {
namespace qco {

`#define` GEN_PASS_DECL_BASISDECOMPOSITION
`#include` "mlir/Dialect/QCO/Transforms/Passes.h.inc"

`#define` GEN_PASS_REGISTRATION
`#include` "mlir/Dialect/QCO/Transforms/Passes.h.inc"

} // namespace qco
} // namespace mlir

2. Integrate into Optimization Stage

Modify CompilerPipeline.cpp line 163:

// Stage 5: Optimization passes
pm.addPass(qco::createBasisDecompositionPass(targetBasis));
// Add other optimization passes as needed
addCleanupPasses(pm);

3. Write Integration Tests

Add tests to test_compiler_pipeline.cpp that verify decomposition actually happens:

/**
 * `@brief` Test: Multi-controlled gate decomposition in optimization stage
 * 
 * `@details`
 * Verifies that high-level gates (e.g., Toffoli) are decomposed into 
 * the target basis during the optimization stage.
 */
TEST_F(CompilerPipelineTest, ToffoliDecomposition) {
  ::qc::QuantumComputation comp(3);
  comp.mcx({0, 1}, 2);  // Toffoli gate

  const auto module = importQuantumCircuit(comp);
  ASSERT_TRUE(module);
  
  // Configure to enable decomposition
  config.targetBasis = GateBasis::CX_RZ_SX;  // Example target basis
  ASSERT_TRUE(runPipeline(module.get()).succeeded());

  // After optimization, the Toffoli should be decomposed
  const auto qcInit = buildQCIR([](mlir::qc::QCProgramBuilder& b) {
    auto reg = b.allocQubitRegister(3, "q");
    b.mcx({reg[0], reg[1]}, reg[2]);
  });
  
  // Expected: decomposed into basis gates (CX, RZ, SX)
  const auto qcoOpt = buildQCOIR([](qco::QCOProgramBuilder& b) {
    auto reg = b.allocQubitRegister(3, "q");
    // Add expected decomposition here
    // This should match what your decomposer produces
    auto q0 = reg[0];
    auto q1 = reg[1]; 
    auto q2 = reg[2];
    // Example decomposition pattern (adjust based on your algorithm):
    q2 = b.h(q2);
    std::tie(q1, q2) = b.cx(q1, q2);
    q2 = b.tdg(q2);
    std::tie(q0, q2) = b.cx(q0, q2);
    q2 = b.t(q2);
    std::tie(q1, q2) = b.cx(q1, q2);
    // ... continue decomposition
  });

  verifyAllStages({
      .qcImport = qcInit.get(),
      .qcoConversion = qcInit.get(),
      .optimization = qcoOpt.get(),  // This is where decomposition happens!
      .qcConversion = nullptr,  // Don't care about later stages for this test
      .qirConversion = nullptr,
  });
}

/**
 * `@brief` Test: U gate decomposition to Clifford+T
 */
TEST_F(CompilerPipelineTest, UGateDecomposition) {
  ::qc::QuantumComputation comp(1);
  comp.u(M_PI/4, M_PI/2, M_PI/3, 0);

  const auto module = importQuantumCircuit(comp);
  ASSERT_TRUE(module);
  ASSERT_TRUE(runPipeline(module.get()).succeeded());

  // Verify that U gate is decomposed during optimization
  // The optimization stage should contain only basis gates
  // Parse the recorded IR and verify no U gates remain
  ASSERT_FALSE(record.afterOptimizationCanon.find("qco.u") != std::string::npos)
      << "U gate should be decomposed in optimization stage";
}

4. Verify Decomposition Correctness

Test that decomposition preserves semantics:

TEST_F(CompilerPipelineTest, DecompositionPreservesSemantics) {
  ::qc::QuantumComputation comp(2);
  comp.mcx({0}, 1);  // CNOT
  
  // Get unitary before decomposition
  auto beforeMatrix = comp.getMatrix();
  
  const auto module = importQuantumCircuit(comp);
  config.targetBasis = GateBasis::CliffordT;
  ASSERT_TRUE(runPipeline(module.get()).succeeded());
  
  // Convert back to QuantumComputation and compare unitaries
  // (You'd need a QC/QIR to QuantumComputation converter for this)
  // ASSERT_TRUE(matricesEqual(beforeMatrix, afterMatrix, tolerance));
}

5. Test Pass Configuration

TEST_F(CompilerPipelineTest, DecompositionRespectsBasisConfig) {
  ::qc::QuantumComputation comp(2);
  comp.swap(0, 1);
  
  const auto module = importQuantumCircuit(comp);
  
  // Test with different basis configurations
  config.targetBasis = GateBasis::Native;  // No decomposition
  ASSERT_TRUE(runPipeline(module.get()).succeeded());
  EXPECT_TRUE(record.afterOptimizationCanon.find("qco.swap") != std::string::npos);
  
  record = CompilationRecord();  // Reset
  
  config.targetBasis = GateBasis::CX_RZ_SX;  // Decompose SWAP
  ASSERT_TRUE(runPipeline(module.get()).succeeded());
  EXPECT_FALSE(record.afterOptimizationCanon.find("qco.swap") != std::string::npos)
      << "SWAP should be decomposed to basis gates";
}

Summary

To properly test decomposition pass application:

  1. Create the pass infrastructure (Passes.h, Passes.td, implementation)
  2. Add it to the pipeline at line 163 in CompilerPipeline.cpp
  3. Write integration tests that verify gates are actually decomposed during the optimization stage
  4. Check the afterOptimization and afterOptimizationCanon fields in CompilationRecord to verify decomposition occurred

The key insight is that you need to compare the QCO IR before and after the optimization stage to verify that high-level gates are replaced with basis gates.

Would you like me to help create a specific decomposition pass or write more detailed test cases for particular gate decompositions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant