Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Closed
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
40 changes: 39 additions & 1 deletion examples/QIR/QirTarget.qs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,24 @@ namespace Microsoft.Quantum.Intrinsic {
return PhysMeasure(bases, qubits);
}

operation MResetZ(qb : Qubit) : Result
{
let res = Mz(qb);
if (res == One)
{
X(qb);
}
return res;
}

operation Reset(qb : Qubit) : Unit
{
if (Mz(qb) == One)
{
X(qb);
}
}

@Inline()
operation Rx(theta : Double, qb : Qubit) : Unit
is Adj {
Expand All @@ -137,7 +155,7 @@ namespace Microsoft.Quantum.Intrinsic {

@Inline()
operation Rz(theta : Double, qb : Qubit) : Unit
is Adj {
is Adj + Ctl {
body (...)
{
PhysRz(theta, qb);
Expand All @@ -146,6 +164,20 @@ namespace Microsoft.Quantum.Intrinsic {
{
PhysRz(-theta, qb);
}
controlled (ctls, ...)
{
PhysRz(theta / 2.0, qb);
CNOT(ctls[0], qb);
PhysRz(-theta / 2.0, qb);
CNOT(ctls[0], qb);
}
controlled adjoint (ctls, ...)
{
PhysRz(-theta / 2.0, qb);
CNOT(ctls[0], qb);
PhysRz(theta / 2.0, qb);
CNOT(ctls[0], qb);
}
}

@Inline()
Expand All @@ -163,4 +195,10 @@ namespace Microsoft.Quantum.Intrinsic {
{
return IntAsDoubleImpl(i);
}

@Inline()
function PI() : Double
{
return 3.14159265357989;
}
}
168 changes: 148 additions & 20 deletions src/QsCompiler/QirGenerator/GenerationContext.cs

Large diffs are not rendered by default.

119 changes: 82 additions & 37 deletions src/QsCompiler/QirGenerator/QirExpressionKindTransformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ public override ResolvedExpression OnBoolLiteral(bool b)
#region Partial applications
abstract class RebuildItem
{
public GenerationContext SharedState { get; set; }
public ITypeRef ItemType { get; set; }
public abstract Value BuildItem(InstructionBuilder builder, ITypeRef captureType, Value capture,
ITypeRef parArgsType, Value parArgs);
Expand Down Expand Up @@ -299,19 +300,25 @@ private class InnerArg : RebuildItem
public override Value BuildItem(InstructionBuilder builder, ITypeRef captureType, Value capture,
ITypeRef parArgsType, Value parArgs)
{
var indices = new Value[] {
builder.Context.CreateConstant(0L),
builder.Context.CreateConstant(this.ArgIndex)
};
var srcPtr = builder.GetElementPtr(parArgsType, parArgs, indices);
var item = builder.Load(this.ItemType, srcPtr);
return item;
if (this.SharedState.IsTupleType(parArgs.NativeType))
{
var indices = new Value[] {
builder.Context.CreateConstant(0L),
builder.Context.CreateConstant(this.ArgIndex)
};
var srcPtr = builder.GetElementPtr(parArgsType, parArgs, indices);
var item = builder.Load(this.ItemType, srcPtr);
return item;
}
else
{
return parArgs;
}
}
}

private class InnerTuple : RebuildItem
{
public GenerationContext SharedState { get; set; }
public ResolvedType TupleType { get; set; }
public readonly List<RebuildItem> Items = new List<RebuildItem>();

Expand Down Expand Up @@ -610,6 +617,7 @@ RebuildItem BuildPartialArgList(ResolvedType argType, TypedExpression arg, List<
{
var rebuild = new InnerArg()
{
SharedState = this.SharedState,
ArgIndex = remainingArgs.Count + 1,
ItemType = this.SharedState.LlvmTypeFromQsharpType(argType)
};
Expand Down Expand Up @@ -639,6 +647,7 @@ RebuildItem BuildPartialArgList(ResolvedType argType, TypedExpression arg, List<
// callable
var rebuild = new InnerCapture()
{
SharedState = this.SharedState,
CaptureIndex = capturedValues.Count + 2,
ItemType = this.SharedState.LlvmTypeFromQsharpType(arg.ResolvedType)
};
Expand Down Expand Up @@ -697,39 +706,74 @@ IrFunction BuildLiftedSpecialization(string name, QsSpecializationKind kind, ITy
this.SharedState.ScopeMgr.OpenScope();

var capturePointer = builder.BitCast(func.Parameters[0], captureType.CreatePointerType());
var parArgsPointer = builder.BitCast(func.Parameters[1], parArgsType.CreatePointerType());
Value innerArgTuple;
if ((kind == QsSpecializationKind.QsControlled) || (kind == QsSpecializationKind.QsControlledAdjoint))
{
// Deal with the extra control qubit arg for controlled and controlled-adjoint
var ctlArgsType = this.SharedState.CurrentContext.CreateStructType(false,
this.SharedState.QirTupleHeader, this.SharedState.QirArray, this.SharedState.QirTuplePointer);
var ctlArgsPointer = builder.BitCast(func.Parameters[1], ctlArgsType.CreatePointerType());
var controlsPointer = builder.GetStructElementPointer(ctlArgsType.CreatePointerType(),
ctlArgsPointer, 1u);
var restPointer = builder.GetStructElementPointer(ctlArgsType.CreatePointerType(), ctlArgsPointer, 2u);
var typedRestPointer = builder.BitCast(restPointer, parArgsType.CreatePointerType());
var restTuple = rebuild.BuildItem(builder, captureType, capturePointer, parArgsType, typedRestPointer);
var size = this.SharedState.ComputeSizeForType(ctlArgsType, builder);
innerArgTuple = builder.Call(this.SharedState.GetRuntimeFunction("tuple_create"), size);
var dummyTupleType = ResolvedType.New(QsResolvedTypeKind.NewTupleType(
(new ResolvedType[] { ResolvedType.New(QsResolvedTypeKind.MissingType) }).ToImmutableArray()));
this.SharedState.ScopeMgr.AddValue(innerArgTuple, dummyTupleType);
var typedNewTuple = builder.BitCast(innerArgTuple, ctlArgsType.CreatePointerType());
var destControlsPointer = builder.GetStructElementPointer(ctlArgsType.CreatePointerType(),
typedNewTuple, 1u);
var controls = builder.Load(this.SharedState.QirArray, controlsPointer);
builder.Store(controls, destControlsPointer);
var destArgsPointer = builder.GetStructElementPointer(ctlArgsType.CreatePointerType(),
typedNewTuple, 2u);
builder.Store(restTuple, destArgsPointer);
// Note that there's a special case if the base specialization only takes a single parameter,
// in which case we don't create the sub-tuple.
if ((parArgsType as IStructType).Members.Count > 2)
{
var ctlArgsType = this.SharedState.CurrentContext.CreateStructType(false,
this.SharedState.QirTupleHeader, this.SharedState.QirArray, this.SharedState.QirTuplePointer);
var ctlArgsPointer = builder.BitCast(func.Parameters[1], ctlArgsType.CreatePointerType());
var controlsPointer = builder.GetElementPtr(ctlArgsType, ctlArgsPointer,
new Value[] { this.SharedState.CurrentContext.CreateConstant(0L), this.SharedState.CurrentContext.CreateConstant(1) });
var restPointer = builder.GetElementPtr(ctlArgsType, ctlArgsPointer,
new Value[] { this.SharedState.CurrentContext.CreateConstant(0L), this.SharedState.CurrentContext.CreateConstant(2) });
var typedRestPointer = builder.BitCast(restPointer, parArgsType.CreatePointerType());
var restTuple = rebuild.BuildItem(builder, captureType, capturePointer, parArgsType, typedRestPointer);
var size = this.SharedState.ComputeSizeForType(ctlArgsType, builder);
innerArgTuple = builder.Call(this.SharedState.GetRuntimeFunction("tuple_create"), size);
this.SharedState.ScopeMgr.AddValue(innerArgTuple);
var typedNewTuple = builder.BitCast(innerArgTuple, ctlArgsType.CreatePointerType());
var destControlsPointer = builder.GetElementPtr(ctlArgsType, typedNewTuple,
new Value[] { this.SharedState.CurrentContext.CreateConstant(0L), this.SharedState.CurrentContext.CreateConstant(1) });
var controls = builder.Load(this.SharedState.QirArray, controlsPointer);
builder.Store(controls, destControlsPointer);
var destArgsPointer = builder.GetElementPtr(ctlArgsType, typedNewTuple,
new Value[] { this.SharedState.CurrentContext.CreateConstant(0L), this.SharedState.CurrentContext.CreateConstant(2) });
builder.Store(restTuple, destArgsPointer);
}
else
{
// First process the incoming argument. Remember, [0] is the %TupleHeader.
var singleArgType = (parArgsType as IStructType).Members[1];
var inputArgsType = this.SharedState.CurrentContext.CreateStructType(false,
this.SharedState.QirTupleHeader, this.SharedState.QirArray, singleArgType);
var inputArgsPointer = builder.BitCast(func.Parameters[1], inputArgsType.CreatePointerType());
var controlsPointer = builder.GetElementPtr(inputArgsType, inputArgsPointer,
new Value[] { this.SharedState.CurrentContext.CreateConstant(0L), this.SharedState.CurrentContext.CreateConstant(1) });
var restPointer = builder.GetElementPtr(inputArgsType, inputArgsPointer,
new Value[] { this.SharedState.CurrentContext.CreateConstant(0L), this.SharedState.CurrentContext.CreateConstant(2) });
var restValue = builder.Load(singleArgType, restPointer);

// OK, now build the full args for the partially-applied callable, other than the controlled qubits
var restTuple = rebuild.BuildItem(builder, captureType, capturePointer, singleArgType, restValue);
// The full args for the inner callable will include the controls
var innerArgType = this.SharedState.CurrentContext.CreateStructType(false,
this.SharedState.QirTupleHeader, this.SharedState.QirArray, restTuple.NativeType);
var size = this.SharedState.ComputeSizeForType(innerArgType, builder);
innerArgTuple = builder.Call(this.SharedState.GetRuntimeFunction("tuple_create"), size);
this.SharedState.ScopeMgr.AddValue(innerArgTuple);
var typedNewTuple = builder.BitCast(innerArgTuple, innerArgType.CreatePointerType());
var destControlsPointer = builder.GetElementPtr(innerArgType, typedNewTuple,
new Value[] { this.SharedState.CurrentContext.CreateConstant(0L), this.SharedState.CurrentContext.CreateConstant(1) });
var controls = builder.Load(this.SharedState.QirArray, controlsPointer);
builder.Store(controls, destControlsPointer);
var destArgsPointer = builder.GetElementPtr(innerArgType, typedNewTuple,
new Value[] { this.SharedState.CurrentContext.CreateConstant(0L), this.SharedState.CurrentContext.CreateConstant(2) });
builder.Store(restTuple, destArgsPointer);
}
}
else
{
var parArgsPointer = builder.BitCast(func.Parameters[1], parArgsType.CreatePointerType());
innerArgTuple = rebuild.BuildItem(builder, captureType, capturePointer, parArgsType, parArgsPointer);
}

var innerCallablePtr = builder.GetStructElementPointer(captureType, capturePointer, 1u);
var innerCallablePtr = builder.GetElementPtr(captureType, capturePointer,
new Value[] { this.SharedState.CurrentContext.CreateConstant(0L), this.SharedState.CurrentContext.CreateConstant(1) });
var innerCallable = builder.Load(this.SharedState.QirCallable, innerCallablePtr);
// Depending on the specialization, we may have to get a different specialization of the callable
var specToCall = GetSpecializedInnerCallable(innerCallable, kind, builder);
Expand All @@ -751,7 +795,7 @@ IrFunction BuildLiftedSpecialization(string name, QsSpecializationKind kind, ITy
QsResolvedTypeKind.Operation pao => pao.Item1.Item1,
_ => throw new InvalidOperationException("Partial application of a non-callable value")
};
var parTupleType = paArgTuple.Resolution switch
var partialArgType = paArgTuple.Resolution switch
{
QsResolvedTypeKind.TupleType pat => this.SharedState.CurrentContext.CreateStructType(false,
this.SharedState.QirTupleHeader, pat.Item.Select(this.SharedState.LlvmTypeFromQsharpType).ToArray()),
Expand Down Expand Up @@ -779,14 +823,16 @@ IrFunction BuildLiftedSpecialization(string name, QsSpecializationKind kind, ITy
capTypeList);
var cap = this.SharedState.CreateTupleForType(capType);
var capture = this.SharedState.CurrentBuilder.BitCast(cap, capType.CreatePointerType());
var callablePointer = this.SharedState.CurrentBuilder.GetStructElementPointer(capType, capture, (uint)1);
var callablePointer = this.SharedState.CurrentBuilder.GetElementPtr(capType, capture,
new Value[] { this.SharedState.CurrentContext.CreateConstant(0L), this.SharedState.CurrentContext.CreateConstant(1) });
var innerCallable = this.EvaluateSubexpression(method);
this.SharedState.CurrentBuilder.Store(innerCallable, callablePointer);
this.SharedState.ScopeMgr.RemovePendingValue(innerCallable);
//AddRef(method.ResolvedType, innerCallable);
for (int n = 0; n < caps.Count; n++)
{
var item = this.SharedState.CurrentBuilder.GetStructElementPointer(capType, capture, (uint)n + 2);
var item = this.SharedState.CurrentBuilder.GetElementPtr(capType, capture,
new Value[] { this.SharedState.CurrentContext.CreateConstant(0L), this.SharedState.CurrentContext.CreateConstant(n+2) });
this.SharedState.CurrentBuilder.Store(caps[n].Item1, item);
this.SharedState.AddRef(caps[n].Item1);
}
Expand Down Expand Up @@ -826,7 +872,7 @@ IrFunction BuildLiftedSpecialization(string name, QsSpecializationKind kind, ITy
if (kinds.Contains(kind))
{
specializations[index] = BuildLiftedSpecialization(liftedName, kind, capType,
parTupleType, rebuild);
partialArgType, rebuild);
}
else
{
Expand Down Expand Up @@ -2030,8 +2076,7 @@ public override ResolvedExpression OnValueTuple(ImmutableArray<TypedExpression>
for (int i = 0; i < vs.Length; i++)
{
var itemValue = this.EvaluateSubexpression(vs[i]);
var itemPointer = this.SharedState.CurrentBuilder.GetStructElementPointer(tupleType, tuplePointer,
(uint)i + 1);
var itemPointer = this.SharedState.GetTupleElementPointer(tupleType, tuplePointer, i + 1);
this.SharedState.CurrentBuilder.Store(itemValue, itemPointer);
}

Expand Down
8 changes: 2 additions & 6 deletions src/QsCompiler/QirGenerator/QirStatementKindTransformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,7 @@ void UpdateTuple(ImmutableArray<TypedExpression> items, Value val)
var tuplePointer = this.SharedState.CurrentBuilder.BitCast(val, tupleType.CreatePointerType());
for (int i = 0; i < items.Length; i++)
{
var itemValuePtr = this.SharedState.CurrentBuilder.GetStructElementPointer(tupleType, tuplePointer,
(uint)i + 1);
var itemValuePtr = this.SharedState.GetTupleElementPointer(tupleType, tuplePointer, i + 1);
var itemValue = this.SharedState.CurrentBuilder.Load(itemTypes[i], itemValuePtr);
UpdateItem(items[i], itemValue);
}
Expand Down Expand Up @@ -528,7 +527,6 @@ void BindVariable(string variable, Value value, ResolvedType type)
// Bind a structured Value to a tuple of variables (which might contain embedded tuples)
void BindTuple(ImmutableArray<SymbolTuple> items, ImmutableArray<ResolvedType> types, Value val)
{
Contract.Assert(items.Length == types.Length, "Tuple to deconstruct doesn't match symbols");
var itemTypes = types.Select(this.SharedState.LlvmTypeFromQsharpType).ToArray();
var tupleType = this.SharedState.CurrentContext.CreateStructType(false, this.SharedState.QirTupleHeader,
itemTypes);
Expand All @@ -542,8 +540,7 @@ void BindTuple(ImmutableArray<SymbolTuple> items, ImmutableArray<ResolvedType> t
}
else
{
var itemValuePtr = this.SharedState.CurrentBuilder.GetStructElementPointer(tupleType, tuplePointer,
(uint)i + 1);
var itemValuePtr = this.SharedState.GetTupleElementPointer(tupleType, tuplePointer, i + 1);
var itemValue = this.SharedState.CurrentBuilder.Load(itemTypes[i], itemValuePtr);
BindItem(item, itemValue, types[i]);
}
Expand Down Expand Up @@ -604,7 +601,6 @@ void AllocateVariable(string variable, ResolvedInitializer init)
// Generate the allocations for a tuple of variables (or embedded tuples)
void AllocateTuple(ImmutableArray<SymbolTuple> items, ImmutableArray<ResolvedInitializer> types)
{
Contract.Assert(items.Length == types.Length, "Initialization list doesn't match symbols");
for (int i = 0; i < items.Length; i++)
{
AllocateItem(items[i], types[i]);
Expand Down
Loading