Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.

Commit a02f79b

Browse files
authored
Allowing to use the LLVM intrinsic readcyclecounter from Q# (#1248)
1 parent 2555a55 commit a02f79b

File tree

5 files changed

+39
-9
lines changed

5 files changed

+39
-9
lines changed

src/QsCompiler/Core/Dependencies.fs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type BuiltIn =
2828
static member ClassicallyControlledNamespace = "Microsoft.Quantum.ClassicalControl"
2929
static member CoreNamespace = "Microsoft.Quantum.Core"
3030
static member DiagnosticsNamespace = "Microsoft.Quantum.Diagnostics"
31+
static member LlvmNamespace = "Microsoft.Quantum.Llvm"
3132
static member IntrinsicNamespace = "Microsoft.Quantum.Intrinsic"
3233
static member StandardArrayNamespace = "Microsoft.Quantum.Arrays"
3334
static member TargetingNamespace = "Microsoft.Quantum.Targeting"
@@ -88,6 +89,8 @@ type BuiltIn =
8889
BuiltIn.EnableTestingViaName
8990
BuiltIn.DumpMachine
9091
BuiltIn.DumpRegister
92+
// in Microsoft.Quantum.Llvm
93+
BuiltIn.ReadCycleCounter
9194
// in Microsoft.Quantum.Canon
9295
BuiltIn.NoOp
9396
// in Microsoft.Quantum.Convert
@@ -250,6 +253,14 @@ type BuiltIn =
250253
Kind = Function(TypeParameters = ImmutableArray.Create "T")
251254
}
252255

256+
// dependencies in Microsoft.Quantum.Llvm
257+
258+
static member ReadCycleCounter =
259+
{
260+
FullName = { Name = "ReadCycleCounter"; Namespace = BuiltIn.LlvmNamespace }
261+
Kind = Operation(TypeParameters = ImmutableArray.Empty, IsSelfAdjoint = false)
262+
}
263+
253264
// dependencies in Microsoft.Quantum.Canon
254265

255266
static member NoOp =

src/QsCompiler/QirGeneration/QIR/Functions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public Functions(GenerationContext sharedState)
6161
optBuiltIn.Add(QsCompiler.BuiltIn.RangeReverse.FullName, this.RangeReverse);
6262
builtIn.Add(QsCompiler.BuiltIn.Message.FullName, this.Message);
6363
builtIn.Add(QsCompiler.BuiltIn.Truncate.FullName, this.DoubleAsInt); // This redundancy needs to be eliminated in the Q# libraries.
64+
builtIn.Add(QsCompiler.BuiltIn.ReadCycleCounter.FullName, this.ReadCycleCounter);
6465
builtIn.Add(QsCompiler.BuiltIn.DumpMachine.FullName, this.DumpMachine);
6566
builtIn.Add(QsCompiler.BuiltIn.DumpRegister.FullName, this.DumpRegister);
6667
optBuiltIn.Add(QsCompiler.BuiltIn.DumpRegister.FullName, this.DumpRegister);
@@ -279,6 +280,13 @@ private IValue Message(IValue arg)
279280
return this.sharedState.Values.Unit;
280281
}
281282

283+
private IValue ReadCycleCounter(IValue arg)
284+
{
285+
var func = this.sharedState.Module.GetIntrinsicDeclaration("llvm.readcyclecounter");
286+
var call = this.sharedState.CurrentBuilder.Call(func);
287+
return this.sharedState.Values.FromSimpleValue(call, Int);
288+
}
289+
282290
private IValue DumpMachine(IValue arg)
283291
{
284292
var value = arg.Value;

src/QsCompiler/QirGeneration/Subtransformations/ExpressionKindTransformation.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,12 @@ IValue InlineSpecialization(QsSpecialization spec, TypedExpression arg)
860860
{
861861
throw new InvalidOperationException("Q# declaration for global callable not found");
862862
}
863+
else if (kind == QsSpecializationKind.QsBody // adjointable and controllable operations are not evaluated by the runtime
864+
&& this.SharedState.Functions.TryEvaluate(callableName, arg, out var evaluated))
865+
{
866+
// deal with recognized callables provided by the runtime
867+
return evaluated;
868+
}
863869
else if (NameGeneration.TryGetTargetInstructionName(callable, out var instructionName))
864870
{
865871
// deal with functions that are part of the target specific instruction set
@@ -1480,14 +1486,9 @@ public override ResolvedExpressionKind OnFunctionCall(TypedExpression method, Ty
14801486
// deal with local values; i.e. callables e.g. from partial applications or stored in local variables
14811487
value = this.InvokeLocalCallable(method, arg);
14821488
}
1483-
else if (this.SharedState.Functions.TryEvaluate(callableName, arg, out var evaluated))
1484-
{
1485-
// deal with recognized runtime functions
1486-
value = evaluated;
1487-
}
14881489
else
14891490
{
1490-
// deal with other global callables
1491+
// deal with global callables
14911492
value = this.InvokeGlobalCallable(callableName, QsSpecializationKind.QsBody, arg);
14921493
}
14931494

src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestBuiltInIntrinsics.qs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace Microsoft.Quantum.Testing.QIR {
55
open Microsoft.Quantum.Intrinsic;
66
open Microsoft.Quantum.Diagnostics;
7+
open Microsoft.Quantum.Llvm;
78

89
newtype Options = (
910
SimpleMessage: (String -> Unit),
@@ -22,7 +23,7 @@ namespace Microsoft.Quantum.Testing.QIR {
2223
}
2324

2425
@EntryPoint()
25-
operation TestBuiltInIntrinsics() : Unit {
26+
operation TestBuiltInIntrinsics() : Int {
2627
let options = DefaultOptions()
2728
w/ SimpleMessage <- Message
2829
w/ DumpToFile <- DumpMachine
@@ -31,6 +32,7 @@ namespace Microsoft.Quantum.Testing.QIR {
3132
options::SimpleMessage("Hello");
3233
options::DumpToFile("pathToFile");
3334
options::DumpToConsole();
35+
return ReadCycleCounter();
3436
}
3537
}
3638

@@ -47,3 +49,10 @@ namespace Microsoft.Quantum.Diagnostics {
4749
body intrinsic;
4850
}
4951
}
52+
53+
namespace Microsoft.Quantum.Llvm {
54+
55+
operation ReadCycleCounter() : Int {
56+
body intrinsic;
57+
}
58+
}

src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestBuiltInIntrinsics1.ll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
define internal void @Microsoft__Quantum__Testing__QIR__TestBuiltInIntrinsics__body() {
1+
define internal i64 @Microsoft__Quantum__Testing__QIR__TestBuiltInIntrinsics__body() {
22
entry:
33
%0 = call { %Callable*, %Callable*, %Callable* }* @Microsoft__Quantum__Testing__QIR__DefaultOptions__body()
44
%1 = bitcast { %Callable*, %Callable*, %Callable* }* %0 to %Tuple*
@@ -50,6 +50,7 @@ entry:
5050
store %String* %24, %String** %27, align 8
5151
call void @__quantum__rt__callable_invoke(%Callable* %19, %Tuple* %25, %Tuple* null)
5252
call void @__quantum__rt__callable_invoke(%Callable* %14, %Tuple* null, %Tuple* null)
53+
%28 = call i64 @llvm.readcyclecounter()
5354
call void @__quantum__rt__capture_update_alias_count(%Callable* %17, i32 -1)
5455
call void @__quantum__rt__callable_update_alias_count(%Callable* %17, i32 -1)
5556
call void @__quantum__rt__capture_update_alias_count(%Callable* %19, i32 -1)
@@ -71,5 +72,5 @@ entry:
7172
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %21, i32 -1)
7273
call void @__quantum__rt__string_update_reference_count(%String* %24, i32 -1)
7374
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %25, i32 -1)
74-
ret void
75+
ret i64 %28
7576
}

0 commit comments

Comments
 (0)