Skip to content
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

Make sure uccsd compiles for quantum devices #2458

Draft
wants to merge 65 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
00aa8d8
Temp
annagrin Nov 12, 2024
1a300ba
Merged with main
annagrin Dec 2, 2024
b1b220c
Add tests
annagrin Dec 9, 2024
0ca3674
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into fi…
annagrin Dec 9, 2024
fac55bd
Revert temp changes
annagrin Dec 9, 2024
ae35d16
TEMP
annagrin Jan 7, 2025
ad486c1
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into fi…
annagrin Jan 22, 2025
4178f0e
Fix bugs
annagrin Jan 29, 2025
cf283a3
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into fi…
annagrin Jan 29, 2025
3c07cad
Add classic opts to LoopUnroll and add tests
annagrin Jan 30, 2025
ff887ea
Remove local mounts
annagrin Jan 30, 2025
718d9ed
DCO Remediation Commit for Anna Gringauze <[email protected]>
annagrin Jan 30, 2025
f33a3b9
Use .inc files instead of splitting patterns out
annagrin Jan 31, 2025
16d8d69
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into fi…
annagrin Jan 31, 2025
0a36b6b
temp
annagrin Feb 4, 2025
ec5468e
temp
annagrin Feb 4, 2025
3dc023f
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into lo…
annagrin Feb 5, 2025
4648b9e
temp
annagrin Feb 5, 2025
150a84e
Add more patterns to loop-unroll
annagrin Feb 6, 2025
5a5f88a
Merge with main
annagrin Feb 6, 2025
591f09d
cleanup
annagrin Feb 7, 2025
377248b
cleanup
annagrin Feb 7, 2025
0ab3a56
Merge with main
annagrin Feb 7, 2025
f08502e
Fix some failing tests
annagrin Feb 7, 2025
2fb2cfe
Fix failing tests
annagrin Feb 7, 2025
6d4291f
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into lo…
annagrin Feb 7, 2025
e714387
DCO Remediation Commit for Anna Gringauze <[email protected]>
annagrin Feb 7, 2025
68b9ba2
Remove parts handled in other CRs
annagrin Feb 7, 2025
74178a8
Merged with main
annagrin Feb 7, 2025
ef0909c
Merged in loop-unroll-additional-opts
annagrin Feb 7, 2025
1e1a4ca
Cleanup
annagrin Feb 7, 2025
b3ec379
Fix test failures
annagrin Feb 8, 2025
9b6fc6a
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into lo…
annagrin Feb 8, 2025
3d3597d
Update write_after_write_elimination.qke
annagrin Feb 8, 2025
6a17b19
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into fi…
annagrin Feb 8, 2025
b537ffe
Fix test failures
annagrin Feb 8, 2025
ee2884c
Update write_after_write_elimination.qke
annagrin Feb 8, 2025
7600781
Update test_kernel_features.py
annagrin Feb 8, 2025
e06980c
`DCO Remediation Commit for Anna Gringauze <[email protected]>
annagrin Feb 8, 2025
032b465
Merge branch 'loop-unroll-additional-opts' of https://github.com/anna…
annagrin Feb 8, 2025
0ddeccf
DCO Remediation Commit for Anna Gringauze <[email protected]>
annagrin Feb 8, 2025
e74b60b
Remove unnecessary changes
annagrin Feb 8, 2025
aba4409
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into fi…
annagrin Feb 8, 2025
1791226
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into lo…
annagrin Feb 8, 2025
a746d83
Fix failed tests
annagrin Feb 8, 2025
b944077
Fix failed tests
annagrin Feb 8, 2025
13cfcad
Fix failed tests
annagrin Feb 9, 2025
bfd4a4c
Run canonical patterns alongside lift-array-alloc
annagrin Feb 9, 2025
a9ec857
Fix failed tests
annagrin Feb 10, 2025
44c845b
Merge branch 'lift-array-alloc-array-copy' of https://github.com/anna…
annagrin Feb 10, 2025
3ce961f
Add classical-optimization pass and pipeline
annagrin Feb 11, 2025
0bdf458
Add more tests
annagrin Feb 11, 2025
0b58beb
Remove unneded comments
annagrin Feb 11, 2025
f9cca25
Remove unneded comments
annagrin Feb 11, 2025
0cff560
Merged with classical-optimization-pipeline2
annagrin Feb 11, 2025
ba7b46d
Use classical optimization pipeline in quantum config files
annagrin Feb 11, 2025
a62cbc7
Revert lift-array-alloc changes
annagrin Feb 11, 2025
96a62e6
Add classical-optimization-pipeline to more backends
annagrin Feb 11, 2025
3b93567
Merge branch 'main' into classical-optimization-pipeline2
annagrin Feb 12, 2025
5564a64
Fixed failing target config tests
annagrin Feb 12, 2025
b2cd5ce
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into fi…
annagrin Feb 12, 2025
75f4cae
Merge branch 'classical-optimization-pipeline2' of https://github.com…
annagrin Feb 12, 2025
672d57f
Address CR comments
annagrin Feb 12, 2025
e178987
Cleanup
annagrin Feb 13, 2025
a93ba6e
Merge branch 'main' of https://github.com/NVIDIA/cuda-quantum into fi…
annagrin Feb 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/cudaq/Optimizer/Dialect/CC/CCOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ def cc_IfOp : CCOp<"if",

let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
let hasCanonicalizer = 1;

let extraClassDeclaration = [{
using RegionBuilderFn = llvm::function_ref<void(mlir::OpBuilder &,
Expand Down
25 changes: 25 additions & 0 deletions include/cudaq/Optimizer/Transforms/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,29 @@ def CombineMeasurements :
}


def CollapseStores : Pass<"collapse-stores", "mlir::func::FuncOp"> {
let summary = "Remove stores that are overriden by other stores.";
let description = [{

Example:
```mlir
%1 = cc.alloca !cc.array<i64 x 1>
%2 = cc.cast %1 : (!cc.ptr<!cc.array<i64 x 1>>) -> !cc.ptr<i64>
cc.store %c0_i64, %2 : !cc.ptr<i64>
// nothing using %2 until the next instruction
cc.store %c1_i64, %2 : !cc.ptr<i64>
```

would be converted to

```mlir
%1 = cc.alloca !cc.array<i64 x 1>
%2 = cc.cast %1 : (!cc.ptr<!cc.array<i64 x 1>>) -> !cc.ptr<i64>
cc.store %c1_i64, %2 : !cc.ptr<i64>
```
}];
}

def CombineQuantumAllocations :
Pass<"combine-quantum-alloc", "mlir::func::FuncOp"> {
let summary = "Combines quake alloca operations.";
Expand Down Expand Up @@ -623,6 +646,8 @@ def LoopUnroll : Pass<"cc-loop-unroll"> {
Option<"signalFailure",
"signal-failure-if-any-loop-cannot-be-completely-unrolled", "bool",
/*default=*/"false", "Signal failure if pass can't unroll all loops.">,
Option<"allowClosedInterval", "allow-closed-interval", "bool",
/*default=*/"true", "Allow loop iterations on a closed interval.">,
Option<"allowBreak", "allow-early-exit", "bool", /*default=*/"false",
"Allow unrolling of loop with early exit (i.e. break statement).">
];
Expand Down
57 changes: 57 additions & 0 deletions lib/Optimizer/Dialect/CC/CCOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2038,6 +2038,63 @@ MutableOperandRange cudaq::cc::ConditionOp::getMutableSuccessorOperands(
return getResultsMutable();
}

//===----------------------------------------------------------------------===//
// IfOp
//===----------------------------------------------------------------------===//

namespace {
/// const prop `cc.if($true)` and `cc.if($false)`
struct EraseConstIf : public OpRewritePattern<cudaq::cc::IfOp> {
using OpRewritePattern::OpRewritePattern;

static bool hasQuantumAllocations(Block &block) {
for (auto &op : block) {
for (auto &region : op.getRegions())
for (auto &b : region)
if (hasQuantumAllocations(b))
return true;

if (auto alloc = dyn_cast<quake::AllocaOp>(&op))
return true;
}
return false;
}

LogicalResult matchAndRewrite(cudaq::cc::IfOp ifOp,
PatternRewriter &rewriter) const override {
auto cond = ifOp.getCondition();
if (auto constCond = cond.getDefiningOp<arith::ConstantOp>()) {
if (auto attr = dyn_cast<BoolAttr>(constCond.getValue())) {
auto value = attr.getValue();
auto block =
value ? ifOp.getThenEntryBlock() : ifOp.getElseEntryBlock();

// Prevent quantum allocations from moving to an outer scope.
if (block && hasQuantumAllocations(*block))
return failure();
annagrin marked this conversation as resolved.
Show resolved Hide resolved

if (block) {
if (auto cont = dyn_cast<cudaq::cc::ContinueOp>(block->back())) {
for (std::size_t i = 0; auto opnd : ifOp.getResults())
rewriter.replaceAllUsesWith(opnd, cont.getOperand(i++));
rewriter.eraseOp(cont);
annagrin marked this conversation as resolved.
Show resolved Hide resolved
}
rewriter.mergeBlockBefore(block, ifOp);
}
rewriter.eraseOp(ifOp);
return success();
}
}
return failure();
}
};
} // namespace

void cudaq::cc::IfOp::getCanonicalizationPatterns(RewritePatternSet &patterns,
MLIRContext *context) {
patterns.add<EraseConstIf>(context);
}

//===----------------------------------------------------------------------===//
// OffsetOfOp
//===----------------------------------------------------------------------===//
Expand Down
4 changes: 4 additions & 0 deletions lib/Optimizer/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ add_cudaq_library(OptTransforms
ApplyOpSpecialization.cpp
ArgumentSynthesis.cpp
BasisConversion.cpp
CollapseStores.cpp
CollapseStoresPatterns.cpp
annagrin marked this conversation as resolved.
Show resolved Hide resolved
CombineMeasurements.cpp
CombineQuantumAlloc.cpp
ConstPropComplex.cpp
Expand All @@ -34,9 +36,11 @@ add_cudaq_library(OptTransforms
GlobalizeArrayValues.cpp
LambdaLifting.cpp
LiftArrayAlloc.cpp
LiftArrayAllocPatterns.cpp
annagrin marked this conversation as resolved.
Show resolved Hide resolved
LinearCtrlRelations.cpp
LoopAnalysis.cpp
LoopNormalize.cpp
LoopNormalizePatterns.cpp
LoopPeeling.cpp
LoopUnroll.cpp
LowerToCFG.cpp
Expand Down
52 changes: 52 additions & 0 deletions lib/Optimizer/Transforms/CollapseStores.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. *
* All rights reserved. *
* *
* This source code and the accompanying materials are made available under *
* the terms of the Apache License 2.0 which accompanies this distribution. *
******************************************************************************/

#include "CollapseStoresPatterns.h"
#include "PassDetails.h"
#include "cudaq/Optimizer/Builder/Intrinsics.h"
#include "cudaq/Optimizer/Dialect/CC/CCOps.h"
#include "cudaq/Optimizer/Dialect/Quake/QuakeOps.h"
#include "cudaq/Optimizer/Transforms/Passes.h"
#include "mlir/Dialect/Complex/IR/Complex.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Dominance.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "mlir/Transforms/Passes.h"

namespace cudaq::opt {
#define GEN_PASS_DEF_COLLAPSESTORES
#include "cudaq/Optimizer/Transforms/Passes.h.inc"
} // namespace cudaq::opt

#define DEBUG_TYPE "collapse-stores"

using namespace mlir;

namespace {
class CollapseStoresPass
: public cudaq::opt::impl::CollapseStoresBase<CollapseStoresPass> {
public:
using CollapseStoresBase::CollapseStoresBase;

void runOnOperation() override {
auto *ctx = &getContext();
auto func = getOperation();

RewritePatternSet patterns(ctx);
patterns.insert<RemoveUselessStorePattern>(ctx);

LLVM_DEBUG(llvm::dbgs() << "Before collapsing stores: " << func << '\n');

if (failed(applyPatternsAndFoldGreedily(func, std::move(patterns))))
signalPassFailure();

LLVM_DEBUG(llvm::dbgs() << "After collapsing stores: " << func << '\n');
}
};
} // namespace
115 changes: 115 additions & 0 deletions lib/Optimizer/Transforms/CollapseStoresPatterns.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*******************************************************************************
* Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. *
* All rights reserved. *
* *
* This source code and the accompanying materials are made available under *
* the terms of the Apache License 2.0 which accompanies this distribution. *
******************************************************************************/

#include "CollapseStoresPatterns.h"
#include "PassDetails.h"
#include "cudaq/Optimizer/Builder/Intrinsics.h"
#include "cudaq/Optimizer/Dialect/CC/CCOps.h"
#include "cudaq/Optimizer/Dialect/Quake/QuakeOps.h"
#include "cudaq/Optimizer/Transforms/Passes.h"
#include "mlir/Dialect/Complex/IR/Complex.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Dominance.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "mlir/Transforms/Passes.h"

#define DEBUG_TYPE "collapse-stores"

using namespace mlir;

/// Remove stores followed by a store to the same pointer
/// if the pointer is not used in between.
/// ```
/// cc.store %c0_i64, %5 : !cc.ptr<i64>
/// // no use of %5 until next line
/// cc.store %3, %5 : !cc.ptr<i64>
/// ───────────────────────────────────────────
/// cc.store %3, %5 : !cc.ptr<i64>
/// ```
LogicalResult
RemoveUselessStorePattern::matchAndRewrite(cudaq::cc::StoreOp store,
PatternRewriter &rewriter) const {
if (isUselessStore(store)) {
rewriter.eraseOp(store);
return success();
}
return failure();
}

/// Detect if the current store can be removed.
bool RemoveUselessStorePattern::isUselessStore(cudaq::cc::StoreOp store) {
Value currentPtr;

if (!isStoreToStack(store))
return false;

auto block = store.getOperation()->getBlock();
for (auto &op : *block) {
if (auto s = dyn_cast<cudaq::cc::StoreOp>(&op)) {
auto nextPtr = s.getPtrvalue();
if (store == s) {
// Start searching from the current store
currentPtr = nextPtr;
} else {
// Found an overriding store, the current store is useless
if (currentPtr == nextPtr)
return true;

// Found a use for a current ptr before the overriding store
if (currentPtr && isUsed(currentPtr, &op))
return false;
}
} else {
// Found a use for a current ptr before the overriding store
if (currentPtr && isUsed(currentPtr, &op))
return false;
}
}
// No multiple stores to the same location found
return false;
}

/// Detect stores to stack locations
/// ```
/// %1 = cc.alloca !cc.array<i64 x 2>
///
/// %2 = cc.cast %1 : (!cc.ptr<!cc.array<i64 x 2>>) -> !cc.ptr<i64>
/// cc.store %c0_i64, %2 : !cc.ptr<i64>
///
/// %3 = cc.compute_ptr %1[1] : (!cc.ptr<!cc.array<i64 x 2>>) -> !cc.ptr<i64>
/// cc.store %c0_i64, %3 : !cc.ptr<i64>
/// ```
bool RemoveUselessStorePattern::isStoreToStack(cudaq::cc::StoreOp store) {
auto ptrOp = store.getPtrvalue();
if (auto cast = ptrOp.getDefiningOp<cudaq::cc::CastOp>())
ptrOp = cast.getOperand();

if (auto computePtr = ptrOp.getDefiningOp<cudaq::cc::ComputePtrOp>())
ptrOp = computePtr.getBase();

if (auto alloca = ptrOp.getDefiningOp<cudaq::cc::AllocaOp>())
return true;

return false;
}

/// Detect if value is used in the op or its nested blocks.
bool RemoveUselessStorePattern::isUsed(Value v, Operation *op) {
for (auto opnd : op->getOperands())
if (opnd == v)
return true;

for (auto &region : op->getRegions())
for (auto &b : region)
for (auto &innerOp : b)
if (isUsed(v, &innerOp))
return true;

return false;
}
60 changes: 60 additions & 0 deletions lib/Optimizer/Transforms/CollapseStoresPatterns.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/****************************************************************-*- C++ -*-****
* Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. *
* All rights reserved. *
* *
* This source code and the accompanying materials are made available under *
* the terms of the Apache License 2.0 which accompanies this distribution. *
******************************************************************************/

#include "PassDetails.h"
#include "cudaq/Optimizer/Builder/Intrinsics.h"
#include "cudaq/Optimizer/Dialect/CC/CCOps.h"
#include "cudaq/Optimizer/Dialect/Quake/QuakeOps.h"
#include "cudaq/Optimizer/Transforms/Passes.h"
#include "mlir/Dialect/Complex/IR/Complex.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Dominance.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "mlir/Transforms/Passes.h"

/// Remove stores followed by a store to the same pointer
/// if the pointer is not used in between.
/// ```
/// cc.store %c0_i64, %5 : !cc.ptr<i64>
/// // no use of %5 until next line
/// cc.store %3, %5 : !cc.ptr<i64>
/// ───────────────────────────────────────────
/// cc.store %3, %5 : !cc.ptr<i64>
/// ```
class RemoveUselessStorePattern
: public mlir::OpRewritePattern<cudaq::cc::StoreOp> {
public:
using OpRewritePattern::OpRewritePattern;

explicit RemoveUselessStorePattern(mlir::MLIRContext *ctx)
: OpRewritePattern(ctx) {}

mlir::LogicalResult
matchAndRewrite(cudaq::cc::StoreOp store,
mlir::PatternRewriter &rewriter) const override;

private:
/// Detect if the current store can be removed.
static bool isUselessStore(cudaq::cc::StoreOp store);

/// Detect stores to stack locations
/// ```
/// %1 = cc.alloca !cc.array<i64 x 2>
///
/// %2 = cc.cast %1 : (!cc.ptr<!cc.array<i64 x 2>>) -> !cc.ptr<i64>
/// cc.store %c0_i64, %2 : !cc.ptr<i64>
///
/// %3 = cc.compute_ptr %1[1] : (!cc.ptr<!cc.array<i64 x 2>>) -> !cc.ptr<i64>
/// cc.store %c0_i64, %3 : !cc.ptr<i64>
/// ```
static bool isStoreToStack(cudaq::cc::StoreOp store);

/// Detect if value is used in the op or its nested blocks.
static bool isUsed(mlir::Value v, mlir::Operation *op);
};
Loading
Loading