Skip to content

Commit f6da850

Browse files
authored
Add support for Adaptive_RIFL QIR programs in GPU simulator (#3039)
This PR adds support for running Adaptive_RIFL QIR programs in the GPU simulator. ## The core idea 1. We compile the adaptive QIR to bytecode. 2. Then, we implement a bytecode interpreter as a GPU shader. 3. Then we upload the bytecode to the GPU and run thousands of adaptive QIR simulations in parallel. ## Current limitations 1. We only support 32-bit arithmetic at the moment 2. The register file size can hold up to 4096 registers, so, programs with more than that number of SSA will throw an error. This limit can be adjusted if we hit it in the future. ## Follow up work 1. Add array support to complete compliance with the Adaptive_RIFLA profile 2. Add Adaptive_RIFLA support to CPU and Clifford simulators
1 parent edebe14 commit f6da850

20 files changed

+8302
-606
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
"""Shared opcode constants for the Adaptive Profile QIR bytecode interpreter.
5+
6+
These constants define the bytecode encoding used by the Python AdaptiveProfilePass
7+
(emitter) and the Rust GPU receiver. Values must stay in sync with the Rust
8+
``bytecode.rs`` module and the WGSL interpreter.
9+
10+
Opcode word layout::
11+
12+
bits [7:0] = primary opcode
13+
bits [15:8] = sub-opcode / condition code
14+
bits [23:16] = flags
15+
16+
Compose via bitwise OR: ``opcode | (sub << 8) | flag``
17+
Example: ``OP_ICMP | (ICMP_SLE << 8) | FLAG_SRC1_IMM``
18+
"""
19+
20+
# ── Flags (pre-shifted to bit 16+) ──────────────────────────────────────────
21+
FLAG_DST_IMM = 1 << 18 # dst field is an immediate value, not a register
22+
FLAG_SRC0_IMM = 1 << 16 # src0 field is an immediate value, not a register
23+
FLAG_SRC1_IMM = 1 << 17 # src1 field is an immediate value, not a register
24+
FLAG_AUX0_IMM = 1 << 19 # aux0 field is an immediate value, not a register
25+
FLAG_AUX1_IMM = 1 << 20 # aux1 field is an immediate value, not a register
26+
FLAG_AUX2_IMM = 1 << 21 # aux2 field is an immediate value, not a register
27+
FLAG_AUX3_IMM = 1 << 22 # aux3 field is an immediate value, not a register
28+
29+
FLAG_FLOAT = 1 << 23 # operation uses float semantics
30+
31+
32+
# ── Control Flow ─────────────────────────────────────────────────────────────
33+
OP_NOP = 0x00
34+
OP_RET = 0x02
35+
OP_JUMP = 0x04
36+
OP_BRANCH = 0x05
37+
OP_SWITCH = 0x06
38+
OP_CALL = 0x07
39+
OP_CALL_RETURN = 0x08
40+
41+
# ── Quantum ──────────────────────────────────────────────────────────────────
42+
OP_QUANTUM_GATE = 0x10
43+
OP_MEASURE = 0x11
44+
OP_RESET = 0x12
45+
OP_READ_RESULT = 0x13
46+
OP_RECORD_OUTPUT = 0x14
47+
48+
# ── Integer Arithmetic ───────────────────────────────────────────────────────
49+
OP_ADD = 0x20
50+
OP_SUB = 0x21
51+
OP_MUL = 0x22
52+
OP_UDIV = 0x23
53+
OP_SDIV = 0x24
54+
OP_UREM = 0x25
55+
OP_SREM = 0x26
56+
57+
# ── Bitwise / Shift ─────────────────────────────────────────────────────────
58+
OP_AND = 0x28
59+
OP_OR = 0x29
60+
OP_XOR = 0x2A
61+
OP_SHL = 0x2B
62+
OP_LSHR = 0x2C
63+
OP_ASHR = 0x2D
64+
65+
# ── Comparison ───────────────────────────────────────────────────────────────
66+
OP_ICMP = 0x30
67+
OP_FCMP = 0x31
68+
69+
# ── Float Arithmetic ─────────────────────────────────────────────────────────
70+
OP_FADD = 0x38
71+
OP_FSUB = 0x39
72+
OP_FMUL = 0x3A
73+
OP_FDIV = 0x3B
74+
75+
# ── Type Conversion ──────────────────────────────────────────────────────────
76+
OP_ZEXT = 0x40
77+
OP_SEXT = 0x41
78+
OP_TRUNC = 0x42
79+
OP_FPEXT = 0x43
80+
OP_FPTRUNC = 0x44
81+
OP_INTTOPTR = 0x45
82+
OP_FPTOSI = 0x46
83+
OP_SITOFP = 0x47
84+
85+
# ── SSA / Data Movement ─────────────────────────────────────────────────────
86+
OP_PHI = 0x50
87+
OP_SELECT = 0x51
88+
OP_MOV = 0x52
89+
OP_CONST = 0x53
90+
91+
# ── ICmp condition codes (sub-opcode, placed in bits[15:8] via << 8) ─────────
92+
# Reference: https://llvm.org/docs/LangRef.html#icmp-instruction
93+
ICMP_EQ = 0
94+
ICMP_NE = 1
95+
ICMP_SLT = 2
96+
ICMP_SLE = 3
97+
ICMP_SGT = 4
98+
ICMP_SGE = 5
99+
ICMP_ULT = 6
100+
ICMP_ULE = 7
101+
ICMP_UGT = 8
102+
ICMP_UGE = 9
103+
104+
# ── FCmp condition codes ─────────────────────────────────────────────────────
105+
# Reference: https://llvm.org/docs/LangRef.html#fcmp-instruction
106+
FCMP_FALSE = 0
107+
FCMP_OEQ = 1
108+
FCMP_OGT = 2
109+
FCMP_OGE = 3
110+
FCMP_OLT = 4
111+
FCMP_OLE = 5
112+
FCMP_ONE = 6
113+
FCMP_ORD = 7
114+
FCMP_UNO = 8
115+
FCMP_UEQ = 9
116+
FCMP_UGT = 10
117+
FCMP_UGE = 11
118+
FCMP_ULT = 12
119+
FCMP_ULE = 13
120+
FCMP_UNE = 14
121+
FCMP_TRUE = 15
122+
123+
# ── Register type tags ───────────────────────────────────────────────────────
124+
REG_TYPE_BOOL = 0
125+
REG_TYPE_I32 = 1
126+
REG_TYPE_I64 = 2
127+
REG_TYPE_F32 = 3
128+
REG_TYPE_F64 = 4
129+
REG_TYPE_PTR = 5
130+
131+
# ── Sentinel values ──────────────────────────────────────────────────────────
132+
VOID_RETURN = 0xFFFFFFFF # Function does not have a return value.

0 commit comments

Comments
 (0)