Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
3c76e08
Initial proposal for a QsPasses structure
troels-im Jul 20, 2021
9eb5c02
Updating CMake
troels-im Jul 20, 2021
6674e24
Adding CI stuff
troels-im Jul 20, 2021
199eed4
Making CLI interface for CI tasks
troels-im Jul 20, 2021
de323ef
Finishing V1 of CI script with updated clang tidy and format
troels-im Jul 21, 2021
cfb4b93
Refactoring CI module
troels-im Jul 21, 2021
d8949bf
Refactoring
troels-im Jul 21, 2021
cc1a0e6
Removing binary IR
troels-im Jul 21, 2021
1a98e31
Updating gitignore
troels-im Jul 21, 2021
74a4924
Creating root tool for performing CI tasks
troels-im Jul 21, 2021
9841c95
Updating documentation
troels-im Jul 21, 2021
1a5e95f
Refactoring pass
troels-im Jul 21, 2021
f8c7a97
Preparing analysis module
troels-im Jul 21, 2021
87c08b9
Adding a style proposal
troels-im Jul 22, 2021
f095508
Adding style proposal
troels-im Jul 22, 2021
b0c63d6
Updating documentation
troels-im Jul 22, 2021
564f518
Template based pass generator
troels-im Jul 22, 2021
c80fd35
Updating template and writing more documentation
troels-im Jul 22, 2021
3078388
Adding introduction on how to create a pass
troels-im Jul 22, 2021
e975b25
Improving code quality
troels-im Jul 22, 2021
06b09ed
Improving code quality
troels-im Jul 22, 2021
fdb465a
Adding namespaces to passes
troels-im Jul 22, 2021
dd810af
Adding comments to the source
troels-im Jul 22, 2021
db6ab19
Merge branch 'main' into feature/llvm-pass-proposal
troels-im Jul 22, 2021
c40796d
Small refactor
troels-im Jul 22, 2021
a23b6b7
Adding QIR example using opt for optimisation and refactoring library…
troels-im Jul 23, 2021
327ff7f
Adding documentation
troels-im Jul 23, 2021
0ee8249
Updating linter and formatter
troels-im Jul 23, 2021
6c3c896
Updating code to meet PR comments
troels-im Jul 26, 2021
df3e4d2
Adding function analysis template
troels-im Jul 26, 2021
62e64cb
Update of template
troels-im Jul 26, 2021
f0c47f2
Adding boiler plate for const size array analysis
troels-im Jul 26, 2021
49fe601
Adding constant allocation identification
troels-im Jul 26, 2021
cc1a979
Removing garbage
troels-im Jul 26, 2021
7319eb4
Adding slightly harder example
troels-im Jul 26, 2021
c051ee6
Updating with additional example
troels-im Jul 26, 2021
6f34ee8
Adding static analysis for qubit allocation
troels-im Jul 27, 2021
bca2646
Refactoring pass
troels-im Jul 27, 2021
75c22f6
More refactoring
troels-im Jul 27, 2021
ab7ddf6
Adding documenation
troels-im Jul 27, 2021
0ae8d26
CI and style
troels-im Jul 27, 2021
436f544
Adding documentation as per request
troels-im Jul 27, 2021
ee7a097
Minor documentation update
troels-im Jul 27, 2021
162d5ce
Adding lit tests
troels-im Jul 27, 2021
c5a1e84
Finalising expansion pass
troels-im Jul 28, 2021
1866d17
Adding expansion pass to allow allocating arrays statically
troels-im Jul 28, 2021
76a534b
Removing leading % from command line snippets
troels-im Jul 30, 2021
37c6665
Merging 'features/llvm-passes'
troels-im Jul 30, 2021
ae42ad2
Fixing broken things from merge
troels-im Jul 30, 2021
c64bf69
Removing garbage
troels-im Jul 30, 2021
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
26 changes: 13 additions & 13 deletions src/Passes/.clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,23 @@ CheckOptions:
- key: readability-identifier-naming.ProtectedMemberSuffix
value: '_'

# Alias
# Type Alias and Enum Types / constants
- key: readability-identifier-naming.TypeAliasCase
value: 'CamelCase'
- key: readability-identifier-naming.TypedefCase
value: 'CamelCase'
- key: readability-identifier-naming.EnumCase
value: 'CamelCase'
- key: readability-identifier-naming.EnumConstantCase
value: 'CamelCase'

# Globals, consts and enums
- key: readability-identifier-naming.GlobalConstantCase
value: 'UPPER_CASE'
- key: readability-identifier-naming.GlobalConstantPrefix
value: 'G_'
- key: readability-identifier-naming.ConstantCase
value: 'UPPER_CASE'

# Functions
- key: readability-identifier-naming.FunctionCase
Expand All @@ -86,18 +98,6 @@ CheckOptions:
- key: readability-identifier-naming.ParameterCase
value: 'lower_case'

# Globals, consts and enums
- key: readability-identifier-naming.GlobalConstantCase
value: 'UPPER_CASE'
- key: readability-identifier-naming.GlobalConstantPrefix
value: 'G_'
- key: readability-identifier-naming.ConstantCase
value: 'UPPER_CASE'
- key: readability-identifier-naming.EnumCase
value: 'CamelCase'
- key: readability-identifier-naming.EnumConstantCase
value: 'CamelCase'

# Macros
- key: readability-identifier-naming.MacroDefinitionCase
value: 'UPPER_CASE'
1 change: 1 addition & 0 deletions src/Passes/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ include_directories(${CMAKE_SOURCE_DIR}/src)

# Adding the libraries
add_subdirectory(libs)
add_subdirectory(tests)
2 changes: 1 addition & 1 deletion src/Passes/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Prefer `#pragma once` over `#ifdef` protection.
## Code TODOs must contain owner name or Github issue

```sh
% ./manage runci
./manage runci
(...)
Passes/src/OpsCounter/OpsCounter.cpp:39:21: error: missing username/bug in TODO [google-readability-todo,-warnings-as-errors]
// TODO: Fails to load if this is present
Expand Down
1 change: 1 addition & 0 deletions src/Passes/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ nothing:
clean:
rm -rf Release/
rm -rf Debug/

20 changes: 10 additions & 10 deletions src/Passes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ and then make your target
make [target]
```

Valid targets are the name of the folders in `libs/` found in the passes root.
The default target is `all`. Other valid targets are the name of the folders in `libs/` found in the passes root.

## Running a pass

Expand All @@ -204,7 +204,7 @@ For a detailed tutorial, see examples.
To make it easy to create a new pass, we have created a few templates to get you started quickly:

```sh
% ./manage create-pass HelloWorld
./manage create-pass HelloWorld
Available templates:

1. Function Pass
Expand All @@ -215,17 +215,17 @@ Select a template:1
At the moment you only have one choice which is a function pass. Over time we will add additional templates. Once you have instantiated your template, you are ready to build it:

```sh
% mkdir Debug
% cd Debug
% cmake ..
mkdir Debug
cd Debug
cmake ..
-- The C compiler identification is AppleClang 12.0.5.12050022
-- The CXX compiler identification is AppleClang 12.0.5.12050022
(...)
-- Configuring done
-- Generating done
-- Build files have been written to: ./qsharp-compiler/src/Passes/Debug

% make
make

[ 25%] Building CXX object libs/CMakeFiles/OpsCounter.dir/OpsCounter/OpsCounter.cpp.o
[ 50%] Linking CXX shared library libOpsCounter.dylib
Expand All @@ -240,9 +240,9 @@ template will not do much except for print the function names of your code. To t
build an IR and run the pass:

```sh
% cd ../examples/ClassicalIrCommandline
% make
% opt -load-pass-plugin ../../Debug/libs/libHelloWorld.{dylib,so} --passes="hello-world" -disable-output classical-program.ll
cd ../examples/ClassicalIrCommandline
make
opt -load-pass-plugin ../../Debug/libs/libHelloWorld.{dylib,so} --passes="hello-world" -disable-output classical-program.ll
```

If everything worked, you should see output like this:
Expand Down Expand Up @@ -303,7 +303,7 @@ that you use a docker image to perform these steps. TODO(TFR): The docker image
One error that you may encounter is that an analysis pass does not load with output similar to this:

```sh
% opt -load-pass-plugin ../../Debug/libQSharpPasses.dylib -enable-debugify --passes="operation-counter" -disable-output classical-program.bc
opt -load-pass-plugin ../../Debug/libQSharpPasses.dylib -enable-debugify --passes="operation-counter" -disable-output classical-program.bc
Failed to load passes from '../../Debug/libQSharpPasses.dylib'. Request ignored.
opt: unknown pass name 'operation-counter'
```
Expand Down
105 changes: 105 additions & 0 deletions src/Passes/docs/continous-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Running tests

In order to run the tests, you first need to build the library. Assuming that this is already done and the corresponding build is in `Debug/`, run the tests from the `Debug` folder:

```
lit tests/ -v
-- Testing: 2 tests, 2 workers --
PASS: Quantum-Passes :: QubitAllocationAnalysis/case1.ll (1 of 2)
PASS: Quantum-Passes :: QubitAllocationAnalysis/case2.ll (2 of 2)

Testing Time: 0.27s
Passed: 2
```

# Continuous integration

This component is the largest part of this PR. The continuous integration component includes:

1. Style formatting to ensure that everything looks the same. This includes checking that relevant copyrights are in place.
2. Static analysis
3. Unit testing

The automatic style enforcement is configurable with the ability to easily add or remove rules. Currently the source pipelines are defined as:

```python
SOURCE_PIPELINES = [
{
"name": "C++ Main",
"src": path.join(PROJECT_ROOT, "libs"),

"pipelines": {
"hpp": [
require_pragma_once,
enforce_cpp_license,
enforce_formatting
],
"cpp": [
enforce_cpp_license,
enforce_formatting
]
}
},
# ...
]
```

This part defines pipelines for `.hpp` files and `.cpp` files allowing the developer to add such requirements such as having copyright in the op of the source file and ensure that formatting follows that given by `.clang-format`.

Each of these CI stages can executed individually using `./manage` or you can run the entire CI process by invoking `./manage runci`. An example of what this may look like is here:

```zsh
./manage runci

2021-07-21 14:38:04,896 - FormatChecker - ERROR - /Users/tfr/Documents/Projects/qsharp-compiler/src/QsPasses/src/OpsCounter/OpsCounter.cpp was not correctly formatted.
2021-07-21 14:38:04,899 - FormatChecker - ERROR - Your code did not pass formatting.

./manage stylecheck --fix-issues
./manage runci

-- Found LLVM 11.1.0
-- Using LLVMConfig.cmake in: /usr/local/opt/llvm@11/lib/cmake/llvm
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/tfr/Documents/Projects/qsharp-compiler/src/QsPasses/Debug
Consolidate compiler generated dependencies of target QSharpPasses
[ 50%] Building CXX object CMakeFiles/QSharpPasses.dir/src/OpsCounter/OpsCounter.cpp.o
[100%] Linking CXX shared library libQSharpPasses.dylib
ld: warning: directory not found for option '-L/usr/local/opt/llvm/lib'
[100%] Built target QSharpPasses
/Users/tfr/Documents/Projects/qsharp-compiler/src/QsPasses/src/OpsCounter/OpsCounter.cpp:29:7: error: invalid case style for class 'LegacyOpsCounterPass' [readability-identifier-naming,-warnings-as-errors]
class LegacyOpsCounterPass : public FunctionPass
^~~~~~~~~~~~~~~~~~~~
CLegacyOpsCounterPass
113345 warnings generated.
Suppressed 113345 warnings (113344 in non-user code, 1 NOLINT).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
1 warning treated as error
2021-07-21 14:38:40,191 - Linter - ERROR - /Users/tfr/Documents/Projects/qsharp-compiler/src/QsPasses/src/OpsCounter/OpsCounter.cpp failed static analysis

# ISSUES FIXED MANUALLY
./manage runci

-- Found LLVM 11.1.0
-- Using LLVMConfig.cmake in: /usr/local/opt/llvm@11/lib/cmake/llvm
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/tfr/Documents/Projects/qsharp-compiler/src/QsPasses/Debug
Consolidate compiler generated dependencies of target QSharpPasses
[ 50%] Building CXX object CMakeFiles/QSharpPasses.dir/src/OpsCounter/OpsCounter.cpp.o
[100%] Linking CXX shared library libQSharpPasses.dylib
ld: warning: directory not found for option '-L/usr/local/opt/llvm/lib'
[100%] Built target QSharpPasses
-- Found LLVM 11.1.0
-- Using LLVMConfig.cmake in: /usr/local/opt/llvm@11/lib/cmake/llvm
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/tfr/Documents/Projects/qsharp-compiler/src/QsPasses/Debug
Consolidate compiler generated dependencies of target QSharpPasses
[100%] Built target QSharpPasses
*********************************
No test configuration file found!
*********************************
```

The key idea here is to make it extremely easy to be complaint with the style guide, correct any issues that might come as a result of static analysis and at the same time enforce this when a PR is made.
38 changes: 38 additions & 0 deletions src/Passes/docs/library-structure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Library structure for passes

An important part of this PR is that it proposes a structure for passes: It is suggested that each pass has their own subcode base. The reason for this proposal is that it makes it very easy to add and remove passes as well as decide which passes to link against. Each pass is kept in its own subdirectory under `libs`:

```
libs
├── CMakeLists.txt
└── OpsCounter
├── OpsCounter.cpp
└── OpsCounter.hpp
```

Adding a new pass is easy using the `manage` tool developed in this PR:

```
./manage create-pass HelloWorld
Available templates:

1. Function Pass

Select a template:1
```

which results in a new pass code in the `libs`:

```
libs
├── CMakeLists.txt
├── HelloWorld
│ ├── HelloWorld.cpp
│ ├── HelloWorld.hpp
│ └── SPECIFICATION.md
└── OpsCounter
├── OpsCounter.cpp
└── OpsCounter.hpp
```

A full example of how to create a basic function pass is included in the README.md file for anyone interested.
8 changes: 4 additions & 4 deletions src/Passes/examples/ClassicalIrCommandline/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ IRs can be represented either by a human readible language or through bytecode.
C programs former is generated by

```sh
% clang -O1 -S -emit-llvm classical-program.c -o classical-program.ll
clang -O1 -S -emit-llvm classical-program.c -o classical-program.ll
```

whereas the latter is generated by executing:

```sh
% clang -O1 -c -emit-llvm classical-program.c -o classical-program.bc
clang -O1 -c -emit-llvm classical-program.c -o classical-program.bc
```

This generates a nice and short IR which makes not too overwhelming to understand what is going on.
Expand All @@ -24,13 +24,13 @@ This generates a nice and short IR which makes not too overwhelming to understan
This part assumes that you have built the Passes library.

```sh
% opt -load ../../{Debug,Release}/libQSharpPasses.{dylib,so} -legacy-operation-counter -analyze classical-program.ll
opt -load ../../{Debug,Release}/libQSharpPasses.{dylib,so} -legacy-operation-counter -analyze classical-program.ll
```

## Next-gen passes

This part assumes that you have built the Passes library.

```sh
% opt -load-pass-plugin ../../{Debug,Release}/libQSharpPasses.{dylib,so} --passes="operation-counter" -disable-output classical-program.bc
opt -load-pass-plugin ../../{Debug,Release}/libs/libQSharpPasses.{dylib,so} --passes="print<operation-counter>" -disable-output classical-program.bc
```
6 changes: 3 additions & 3 deletions src/Passes/examples/OptimisationUsingOpt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ namespace Example {
You find the code for this in the folder `SimpleExample`. To generate a QIR for this code, go to the folder and run

```sh
% cd SimpleExample/
% dotnet clean SimpleExample.csproj
cd SimpleExample/
dotnet clean SimpleExample.csproj
(...)
% dotnet build SimpleExample.csproj -c Debug
dotnet build SimpleExample.csproj -c Debug
```

If everything went well, you should now have a subdirectory called `qir` and inside `qir`, you will find `SimpleExample.ll`. Depending on your compiler,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <vector>

void QuantumFunction(int32_t nQubits)
{
volatile uint64_t x = 3;
for (uint64_t i = 0; i < x; ++i)
{
nQubits += nQubits;
}
int32_t qubits[nQubits];
}

int main()
{
QuantumFunction(10);
QuantumFunction(3);
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.Quantum.Sdk/0.18.2106148911">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<QirGeneration>true</QirGeneration>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace Example {
@EntryPoint()
operation Main() : Int
{

QuantumProgram(3,2,1);
QuantumProgram(4,X(2),4);
return 0;
}

function X(value: Int): Int
{
return 3 * value;
}

operation QuantumProgram(x: Int, h: Int, g: Int) : Unit {
let z = x * (x + 1) - 47;
let y = 3 * x;

use qubits0 = Qubit[9];
use qubits1 = Qubit[(y - 2)/2-z];
use qubits2 = Qubit[y - g];
use qubits3 = Qubit[h];
use qubits4 = Qubit[X(x)];

for idxIteration in 0..g {
//Message(idxIteration);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
analysis-example.ll:
dotnet build ConstSizeArray.csproj
opt -S qir/ConstSizeArray.ll -O1 > ../analysis-example.ll
make clean

comparison:
clang++ -S -emit-llvm -std=c++14 -stdlib=libc++ Comparison.cpp -o comparison.ll

clean:
rm -rf bin
rm -rf obj
rm -rf qir

Loading