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
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
4 changes: 2 additions & 2 deletions src/QsCompiler/QirGeneration/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1099,7 +1099,7 @@ private Value ConditionalEvaluation(Value condition, Func<IValue>? onCondTrue =
throw new InvalidOperationException("a default value is required if either onCondTrue or onCondFalse is null");
}

var defaultRequiresRefCount = increaseReferenceCount && defaultValue != null && this.ScopeMgr.RequiresReferenceCount(defaultValue.LlvmType);
var defaultRequiresRefCount = increaseReferenceCount && defaultValue != null && ScopeManager.RequiresReferenceCount(defaultValue.LlvmType);
var requiresTrueBlock = onCondTrue != null || defaultRequiresRefCount;
var requiresFalseBlock = onCondFalse != null || defaultRequiresRefCount;

Expand All @@ -1126,7 +1126,7 @@ IValue ProcessBlock(Func<IValue>? evaluate)
{
this.ScopeMgr.OpenScope();
var evaluated = evaluate?.Invoke() ?? defaultValue!;
this.ScopeMgr.CloseScope(evaluated, false); // force that the ref count is increased within the branch
this.ScopeMgr.CloseScope(evaluated); // forces that the ref count is increased within the branch
return evaluated;
}
else
Expand Down
182 changes: 79 additions & 103 deletions src/QsCompiler/QirGeneration/ScopeManager.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,13 @@ public override QsStatementKind OnConditionalStatement(QsConditionalStatement st
this.SharedState.EndBranch();
}

// Finally, set the continuation block as current or prune it if it is unused.
if (contBlockUsed)
// Finally, set the continuation block as current and prune it if it is unused.
this.SharedState.SetCurrentBlock(contBlock);
if (!contBlockUsed)
{
this.SharedState.SetCurrentBlock(contBlock);
}
else
{
this.SharedState.CurrentFunction.BasicBlocks.Remove(contBlock);
// This is the savest option to deal with this case from a code rubustness perspective.
// The additional code blocks that don't have any predecessors are better trimmed in a separate pass over the generated ir.
this.OnFailStatement(SyntaxGenerator.StringLiteral("reached unreachable code...", ImmutableArray<TypedExpression>.Empty));
}
return QsStatementKind.EmptyStatement;
}
Expand Down Expand Up @@ -417,7 +416,7 @@ public override QsStatementKind OnRepeatStatement(QsRepeatStatement stm)
// We need to make sure to properly invoke all calls to unreference, release, and remove alias counts
// for variables and values in the repeat-block after the statement ends.
this.SharedState.SetCurrentBlock(contBlock);
this.SharedState.ScopeMgr.ExitScope(false);
this.SharedState.ScopeMgr.ExitScope();

this.SharedState.SetCurrentBlock(fixupBlock);
this.Transformation.Statements.OnScope(stm.FixupBlock.Body);
Expand Down
3 changes: 2 additions & 1 deletion src/QsCompiler/Tests.Compiler/QirTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ let ``QIR inlined call`` () = qirTest true "TestInline"
let ``QIR alias counts`` () = qirTest false "TestAliasCounts"

[<Fact>]
let ``QIR reference counts`` () = qirTest false "TestReferenceCounts"
let ``QIR reference counts`` () =
qirMultiTest false "TestReferenceCounts" [ "TestReferenceCounts1"; "TestReferenceCounts2" ]

[<Fact>]
let ``QIR built-in functions`` () = qirTest false "TestBuiltIn"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ then0__1: ; preds = %entry

else__1: ; preds = %entry
ret i1 %e

continue__1: ; No predecessors!
%1 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @0, i32 0, i32 0))
call void @__quantum__rt__fail(%String* %1)
unreachable
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,11 @@ else__1: ; preds = %entry
call void @__quantum__rt__array_update_alias_count(%Array* %arg__1, i32 -1)
call void @__quantum__rt__tuple_update_alias_count(%Tuple* %1, i32 -1)
ret i64 0

continue__1: ; No predecessors!
%4 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @6, i32 0, i32 0))
call void @__quantum__rt__array_update_alias_count(%Array* %arg__1, i32 -1)
call void @__quantum__rt__tuple_update_alias_count(%Tuple* %1, i32 -1)
call void @__quantum__rt__fail(%String* %4)
unreachable
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ then0__2: ; preds = %then0__1
else__2: ; preds = %then0__1
ret i64 2

continue__2: ; No predecessors!
%0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @3, i32 0, i32 0))
call void @__quantum__rt__fail(%String* %0)
unreachable

else__1: ; preds = %entry
br i1 %branch2, label %then0__3, label %else__3

Expand All @@ -19,4 +24,14 @@ then0__3: ; preds = %else__1

else__3: ; preds = %else__1
ret i64 4

continue__3: ; No predecessors!
%1 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @4, i32 0, i32 0))
call void @__quantum__rt__fail(%String* %1)
unreachable

continue__1: ; No predecessors!
%2 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @5, i32 0, i32 0))
call void @__quantum__rt__fail(%String* %2)
unreachable
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,21 @@

namespace Microsoft.Quantum.Testing.QIR {

newtype HasString = (
Value: String,
Data: Double[]
);

operation TestPendingRefCountIncreases(cond : Bool) : HasString {
let s = HasString("<", [0.0]);
let updated = s w/ Data <- [0.1, 0.2];
if cond {
return s;
} else {
return s;
}
}

function TestRefCountsForItemUpdate(cond : Bool) : Unit {
mutable ops = new Int[][5];
if (cond) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
define { %String*, %Array* }* @Microsoft__Quantum__Testing__QIR__TestPendingRefCountIncreases__body(i1 %cond) {
entry:
%0 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @0, i32 0, i32 0))
%1 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 1)
%2 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %1, i64 0)
%3 = bitcast i8* %2 to double*
store double 0.000000e+00, double* %3, align 8
%s = call { %String*, %Array* }* @Microsoft__Quantum__Testing__QIR__HasString__body(%String* %0, %Array* %1)
%4 = getelementptr inbounds { %String*, %Array* }, { %String*, %Array* }* %s, i32 0, i32 1
%5 = load %Array*, %Array** %4, align 8
call void @__quantum__rt__array_update_alias_count(%Array* %5, i32 1)
%6 = bitcast { %String*, %Array* }* %s to %Tuple*
call void @__quantum__rt__tuple_update_alias_count(%Tuple* %6, i32 1)
%7 = call %Tuple* @__quantum__rt__tuple_copy(%Tuple* %6, i1 false)
%updated = bitcast %Tuple* %7 to { %String*, %Array* }*
%8 = getelementptr inbounds { %String*, %Array* }, { %String*, %Array* }* %updated, i32 0, i32 1
%9 = call %Array* @__quantum__rt__array_create_1d(i32 8, i64 2)
%10 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %9, i64 0)
%11 = bitcast i8* %10 to double*
%12 = call i8* @__quantum__rt__array_get_element_ptr_1d(%Array* %9, i64 1)
%13 = bitcast i8* %12 to double*
store double 1.000000e-01, double* %11, align 8
store double 2.000000e-01, double* %13, align 8
store %Array* %9, %Array** %8, align 8
call void @__quantum__rt__array_update_alias_count(%Array* %9, i32 1)
call void @__quantum__rt__tuple_update_alias_count(%Tuple* %7, i32 1)
br i1 %cond, label %then0__1, label %else__1

then0__1: ; preds = %entry
call void @__quantum__rt__array_update_alias_count(%Array* %5, i32 -1)
call void @__quantum__rt__tuple_update_alias_count(%Tuple* %6, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %9, i32 -1)
call void @__quantum__rt__tuple_update_alias_count(%Tuple* %7, i32 -1)
call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %1, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %9, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %7, i32 -1)
ret { %String*, %Array* }* %s

else__1: ; preds = %entry
call void @__quantum__rt__array_update_alias_count(%Array* %5, i32 -1)
call void @__quantum__rt__tuple_update_alias_count(%Tuple* %6, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %9, i32 -1)
call void @__quantum__rt__tuple_update_alias_count(%Tuple* %7, i32 -1)
call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %1, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %9, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %7, i32 -1)
ret { %String*, %Array* }* %s

continue__1: ; No predecessors!
%14 = call %String* @__quantum__rt__string_create(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @1, i32 0, i32 0))
%15 = getelementptr inbounds { %String*, %Array* }, { %String*, %Array* }* %s, i32 0, i32 0
%16 = load %String*, %String** %15, align 8
call void @__quantum__rt__array_update_alias_count(%Array* %5, i32 -1)
call void @__quantum__rt__tuple_update_alias_count(%Tuple* %6, i32 -1)
call void @__quantum__rt__array_update_alias_count(%Array* %9, i32 -1)
call void @__quantum__rt__tuple_update_alias_count(%Tuple* %7, i32 -1)
call void @__quantum__rt__string_update_reference_count(%String* %0, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %1, i32 -1)
call void @__quantum__rt__string_update_reference_count(%String* %16, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %5, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %6, i32 -1)
call void @__quantum__rt__array_update_reference_count(%Array* %9, i32 -1)
call void @__quantum__rt__tuple_update_reference_count(%Tuple* %7, i32 -1)
call void @__quantum__rt__fail(%String* %14)
unreachable
}
5 changes: 4 additions & 1 deletion src/QsCompiler/Tests.Compiler/Tests.Compiler.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,10 @@
<Content Include="TestCases\QirTests\TestRange.qs">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="TestCases\QirTests\TestReferenceCounts.ll">
<Content Include="TestCases\QirTests\TestReferenceCounts1.ll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="TestCases\QirTests\TestReferenceCounts2.ll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="TestCases\QirTests\TestReferenceCounts.qs">
Expand Down