7b22817a8a76f8e6b7ae646d12e96e59c444e619
[WebKit-https.git] / Websites / webkit.org / docs / b3 / intermediate-representation.html
1 <html>
2   <head>
3     <title>B3 Intermediate Representation</title>
4     <link rel="stylesheet" type="text/css" href="style.css">
5   </head>
6   <body>
7     <h1><a href="index.html">Bare Bones Backend</a> / B3 Intermediate Representation</h1>
8     <p>B3 IR is a C-like SSA representation of a procedure.  A procedure has a root block at
9       which it starts execution when it is invoked.  A procedure does not have to terminate, but
10       if it does, then it can be either due to a Return, which gracefully returns some value, or
11       by a side-exit at designated instructions.  B3 gives the client a lot of flexibility to
12       implement many different kinds of side-exits.</p>
13     
14     <p>B3 is designed to represent procedures for the purpose of transforming them.  Knowing
15       what transformations are legal requires knowing what a procedure does.  A transformation
16       is valid if it does not change the observable behavior of a procedure.  This document
17       tells you what B3 procedures do by telling you what each construct in B3 IR does.</p>
18     
19     <h2>Procedure</h2>
20
21     <p>The parent object of all things in B3 is the Procedure.  Every time you want to compile
22       something, you start by creating a Procedure.  The lifecycle of a Procedure is
23       usually:</p>
24
25     <ol>
26       <li>Create the Procedure.</li>
27       <li>Populate the Procedure with code.</li>
28       <li>Use either the <a href="http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/B3Compilation.h">high-level
29           Compilation API</a> or the
30         <a href="http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/B3Generate.h">low-level
31           generation API</a>.</li>
32     </ol>
33
34     <p>The act of compiling the Procedure changes it in-place, making it unsuitable for
35       compiling again.  Always create a new Procedure every time you want to compile
36       something.</p>
37
38     <h2>Types</h2>
39
40     <p>B3 has a trivial type system with only five types:</p>
41
42     <dl>
43       <dt>Void</dt>
44       <dd>Used to say that an instruction does not return a value.</dd>
45
46       <dt>Int32</dt>
47       <dd>32-bit integer.  Integers don't have sign, but operations on them do.</dd>
48
49       <dt>Int64</dt>
50       <dd>64-bit integer.</dd>
51
52       <dt>Float</dt>
53       <dd>32-bit binary floating point number.</dd>
54
55       <dt>Double</dt>
56       <dd>64-bit binary floating point number.</dd>
57     </dl>
58
59     <h2>Values</h2>
60
61     <p>Variables, and the instructions that define them, are represented using the Value object.
62       The Value object has a return type, an opcode, and zero or more children.  Children are
63       references to other Values.  Those values are used as input to the instruction that
64       computes this value.</p>
65     <p>Values also have a unique 32-bit index that is used as the name.</p>
66     
67     <p>Example:</p>
68
69     <pre><code>Int32 @3 = Add(@1, @2)</code></pre>
70
71     <p>This represents a single Value instance.  Its index is 3.  It is an Int32.  The opcode is
72       Add, and its children are @1 and @2.</p>
73
74     <p>Values may also have additional meta-data.  We use special subclasses of the B3::Value
75       class for values that need meta-data.  For example, the Load value needs a 32-bit offset
76       for the load.  We use the MemoryValue class for memory-accessing values, which all have
77       such an offset.</p>
78
79     <h2>Stack Slot</h2>
80
81     <p>B3 exposes the concept of stack-allocated data and gives the client a lot of control.
82       You can force stack slots to end up at a particular offset from the frame pointer, though
83       this is very dangerous.  After compilation is done, you can get the selected frame pointer
84       offset from any stack slot.  Usually, you let B3 select where stack slots go, and then use
85       the StackSlot API to get its FP offset after compilation.</p>
86
87     <p>Stack slots are also used for creating non-SSA variables with the intention of having B3
88       convert them into SSA.  There are two kinds of stack lots.</p>
89
90     <dl>
91       <dt>Anonymous</dt>
92       <dd>Anonymous stack slots are used to represent local variables that aren't in SSA form.
93         B3 is allowed to assume that nobody will store to an anonymous stack slot except through
94         Store instructions in the B3 procedure.  B3 is allowed to assume that a Store that does
95         not write to the entire anonymous stack slot leaves the unwritten part in an undefined
96         state.  Usually, anonymous stack slots are allocated to have the same size as the type
97         of variable they are being used to represent.</dd>
98
99       <dt>Locked</dt>
100       <dd>These stack slots are assumed to operate "as if" they were in the heap, in the sense
101         that the may get read or written using operations not visible in B3 IR.</dd>
102     </dl>
103
104     <p>The fixSSA() phase will convert anonymous stack slots to SSA.</p>
105
106     <h2>Control flow</h2>
107
108     <p>B3 represents control flow using basic blocks.  Each basic block may have zero or more
109       predecessors.  Each basic block may have zero or more successors.  The successors are
110       controlled by the basic block's last Value, which must be a ControlValue instance.</p>
111
112     <p>Each basic block contains a Vector&lt;Value*&gt; as the contents of the block.</p>
113
114     <h2>Opcodes</h2>
115
116     <p>This section describes opcodes in the following format:</p>
117
118     <dl>
119       <dt>Int32 Foo(Int64, Double)</dt>
120       <dd>This describes an opcode named Foo that uses Int32 as its return type and takes two
121         children - one of type Int64 and another of type Double.</dd>
122     </dl>
123
124     <p>We sometimes use the wildcard type T to represent polymorphic operations, like "T Add(T,
125       T)".  This means that the value must take two children of the same type and returns a
126       value of that type.  We use the type IntPtr to mean either Int32, or Int64, depending on
127       the platform.</p>
128
129     <h3>Opcode descriptions</h3>
130
131     <dl>
132       <dt>Void Nop()</dt>
133       <dd>The empty value.  Instead of removing Values from basic blocks, most optimizations
134         convert them to Nops.  Various phases run fix-up where all Nops are removed in one pass.
135         It's common to see Nops in intermediate versions of B3 IR during optimizations.  Nops
136         never lead to any code being generated and they do not impede optimizations, so they are
137         usually harmless.  You can convert a Value to a Nop by doing convertToNop().</dd>
138
139       <dt>T Identity(T)</dt>
140       <dd>Returns the passed value.  May be used for any type except Void.  Instead of replacing
141         all uses of a Value with a different Value, most optimizations convert them to Identity.
142         Various phases run fix-up where all uses of Identity are replaced with the Identity's
143         child (transitively, so Identity(Identity(Identity(@x))) is changed to just @x).  Even
144         the instruction selector "sees through" Identity.  You can remove all references to
145         Identity in any value by calling Value::performSubstitution().  You can convert a Value
146         to an Identity by doing convertToIdentity(otherValue).  If the value is Void,
147         convertToIdentity() converts it to a Nop instead.</dd>
148
149       <dt>Int32 Const32(constant)</dt>
150       <dd>32-bit integer constant.  Must use the Const32Value class, which has space for the
151         int32_t constant.</dd>
152
153       <dt>Int64 Const64(constant)</dt>
154       <dd>64-bit integer constant.  Must use the Const64Value class, which has space for the
155         int64_t constant.</dd>
156
157       <dt>Float ConstFloat(constant)</dt>
158       <dd>Float constant.  Must use the ConstFloatValue class, which has space for the float constant.</dd>
159
160       <dt>Double ConstDouble(constant)</dt>
161       <dd>Double constant.  Must use the ConstDoubleValue class, which has space for the double constant.</dd>
162
163       <dt>IntPtr SlotBase(stackSlot)</dt>
164       <dd>Returns a pointer to the base of the given stack slot.  Must use the SlotBaseValue
165         class.</dd>
166
167       <dt>IntPtr|Double ArgumentReg(%register)</dt>
168       <dd>Returns the value that the given register had at the prologue of the procedure.  It
169         returns IntPtr for general-purpose registers and Double for FPRs.  Must use the
170         ArgumentRegValue class.</dd>
171
172       <dt>IntPtr FramePointer()</dt>
173       <dd>Returns the value of the frame pointer register.  B3 procedures alway use a frame
174         pointer ABI, and the frame pointer is always guaranteed to have this value anywhere
175         inside the procedure.</dd>
176
177       <dt>T Add(T, T)</dt>
178       <dd>Works with any type except Void.  For integer types, this represents addition with
179         wrap-around semantics.  For floating point types, this represents addition according to
180         the IEEE 854 spec.  B3 does not have any notion of "fast math".  A transformation over
181         floating point code is valid if the new code produces exactly the same value, bit for
182         bit.</dd>
183
184       <dt>T Sub(T, T)</dt>
185       <dd>Works with any type except Void.  For integer types, this represents subtraction with
186         wrap-around semantics.  For floating point types, this represents subtraction according
187         to the IEEE 854 spec.</dd>
188
189       <dt>T Mul(T, T)</dt>
190       <dd>Works with any type except Void.  For integer types, this represents multiplication
191         with wrap-around semantics.  For floating point types, this represents multiplication
192         according to the IEEE 854 spec.</dd>
193
194       <dt>T Div(T, T)</dt>
195       <dd>Works with any type except Void.  For integer types, this represents signed division
196         with round-to-zero.  Its behavior is undefined for x/0 or -2`^`31/-1.  For floating
197         point types, this represents division according to the IEEE 854 spec.</dd>
198
199       <dt>T Mod(T, T)</dt>
200       <dd>Works with any type except Void.  For integer types, this represents signed modulo.
201         Its behavior is undefined for x%0 or -2`^`31%-1.  For floating point types, this
202         represents modulo according to "fmod()".</dd>
203
204       <dt>T Neg(T)</dt>
205       <dd>Works with any type except Void.  For integer types, this represents twos-complement
206         negation.  For floating point types, this represents negation according to the IEEE
207         spec.</dd>
208
209       <dt>T ChillDiv(T, T)</dt>
210       <dd>Chill division.  Valid for Int32 and Int64.  An operation is said to be chill if it
211         returns a sensible value whenever its non-chill form would have had undefined behavior.
212         ChillDiv turns x/0 into 0 and -2`^`31/-1 into -2`^`31.  This is a separate opcode
213         because it's exactly the semantics of division on ARM64, and it's also exactly the
214         semantics that JavaScript wants for "(x/y)|0".</dd>
215
216       <dt>T ChillMod(T, T)</dt>
217       <dd>Chill modulo.  Valid for Int32 and Int64.  ChllMod turns x%0 into 0 and -2`^`31%-1
218         into 0.</dd>
219
220       <dt>T BitAnd(T, T)</dt>
221       <dd>Bitwise and.  Valid for Int32 and Int64.</dd>
222
223       <dt>T BitOr(T, T)</dt>
224       <dd>Bitwise or.  Valid for Int32 and Int64.</dd>
225
226       <dt>T BitXor(T, T)</dt>
227       <dd>Bitwise xor.  Valid for Int32 and Int64.</dd>
228
229       <dt>T Shl(T, Int32)</dt>
230       <dd>Shift left.  Valid for Int32 and Int64.  The shift amount is always Int32.  Only the
231         low 31 bits of the shift amount are used for Int32.  Only the low 63 bits of the shift
232         amount are used for Int64.</dd>
233
234       <dt>T SShr(T, Int32)</dt>
235       <dd>Shift right with sign extension.  Valid for Int32 and Int64.  The shift amount is
236         always Int32.  Only the low 31 bits of the shift amount are used for Int32.  Only the
237         low 63 bits of the shift amount are used for Int64.</dd>
238
239       <dt>T ZShr(T, Int32)</dt>
240       <dd>Shift right with zero extension.  Valid for Int32 and Int64.  The shift amount is
241         always Int32.  Only the low 31 bits of the shift amount are used for Int32.  Only the
242         low 63 bits of the shift amount are used for Int64.</dd>
243
244       <dt>T Clz(T)</dt>
245       <dd>Count leading zeroes.  Valid for Int32 and Int64.</dd>
246
247       <dt>T Abs(T)</dt>
248       <dd>Absolute value.  Valid for Float and Double.</dd>
249
250       <dt>T Ceil(T)</dt>
251       <dd>Ceiling.  Valid for Float and Double.</dd>
252
253       <dt>T Sqrt(T)</dt>
254       <dd>Square root.  Valid for Float and Double.</dd>
255
256       <dt>U BitwiseCast(T)</dt>
257       <dd>If T is Int32 or Int64, it returns the bitwise-corresponding Float or Double,
258         respectively.  If T is Float or Double, it returns the bitwise-corresponding Int32 or
259         Int64, respectively.</dd>
260
261       <dt>Int32 SExt8(Int32)</dt>
262       <dd>Fills the top 24 bits of the integer with the low byte's sign extension.</dd>
263
264       <dt>Int32 SExt16(Int32)</dt>
265       <dd>Fills the top 16 bits of the integer with the low short's sign extension.</dd>
266
267       <dt>Int64 SExt32(Int32)</dt>
268       <dd>Returns a 64-bit integer such that the low 32 bits are the given Int32 value and the
269         high 32 bits are its sign extension.</dd>
270
271       <dt>Int64 ZExt32(Int32)</dt>
272       <dd>Returns a 64-bit integer such that the low 32 bits are the given Int32 value and the
273         high 32 bits are zero.</dd>
274
275       <dt>Int32 Trunc(Int64)</dt>
276       <dd>Returns the low 32 bits of the 64-bit value.</dd>
277
278       <dt>Double IToD(T)</dt>
279       <dd>Converts the given integer into a double.  Value for Int32 or Int64 inputs.</dd>
280
281       <dt>Double FloatToDouble(Float)</dt>
282       <dd>Converts the given float into a double.</dd>
283
284       <dt>Float DoubleToFloat(Double)</dt>
285       <dd>Converts the given double into a float.</dd>
286
287       <dt>Int32 Equal(T, T)</dt>
288       <dd>Compares the two values.  If they are equal, return 1; else return 0.  Valid for all
289         types except Void.  Integer comparisons simply compare all bits.  Floating point
290         comparisons mostly compare bits, but have some corner cases: positive zero and negative
291         zero are considered equal, and they return false when either value is NaN.</dd>
292
293       <dt>Int32 NotEqual(T, T)</dt>
294       <dd>The opposite of Equal().  NotEqual(@x, @y) yields the same result as BitXor(Equal(@x,
295         @y), 1).</dd>
296
297       <dt>Int32 LessThan(T, T)</dt>
298       <dd>Returns 1 if the left value is less than the right one, 0 otherwise.  Does a signed
299         comparison for integers.  For floating point comparisons, this has the usual caveats
300         with respect to negative zero and NaN.</dd>
301
302       <dt>Int32 GreaterThan(T, T)</dt>
303       <dd>Returns 1 if the left value is greater than the right one, 0 otherwise.  Does a signed
304         comparison for integers.  For floating point comparisons, this has the usual caveats
305         with respect to negative zero and NaN.</dd>
306
307       <dt>Int32 LessEqual(T, T)</dt>
308       <dd>Returns 1 if the left value is less than or equal to the right one, 0 otherwise.  Does
309         a signed comparison for integers.  For floating point comparisons, this has the usual
310         caveats with respect to negative zero and NaN.</dd>
311
312       <dt>Int32 GreaterEqual(T, T)</dt>
313       <dd>Returns 1 if the left value is greater than or equal to the right one, 0 otherwise.
314         Does a signed comparison for integers.  For floating point comparisons, this has the
315         usual caveats with respect to negative zero and NaN.</dd>
316
317       <dt>Int32 Above(T, T)</dt>
318       <dd>Unsigned integer comparison, valid for Int32 and Int64 only.  Returns 1 if the left
319         value is unsigned-greater-than the right one, 0 otherwise.</dd>
320
321       <dt>Int32 Below(T, T)</dt>
322       <dd>Unsigned integer comparison, valid for Int32 and Int64 only.  Returns 1 if the left
323         value is unsigned-less-than the right one, 0 otherwise.</dd>
324
325       <dt>Int32 AboveEqual(T, T)</dt>
326       <dd>Unsigned integer comparison, valid for Int32 and Int64 only.  Returns 1 if the left
327         value is unsigned-greater-than-or-equal the right one, 0 otherwise.</dd>
328
329       <dt>Int32 BelowEqual(T, T)</dt>
330       <dd>Unsigned integer comparison, valid for Int32 and Int64 only.  Returns 1 if the left
331         value is unsigned-less-than-or-equal the right one, 0 otherwise.</dd>
332
333       <dt>Int32 EqualOrUnordered(T, T)</dt>
334       <dd>Floating point comparison, valid for Float and Double only.  Returns 1 if the left
335         value is equal to the right one or if either value is NaN.  Returns 0 otherwise.</dd>
336
337       <dt>T Select(U, T, T)</dt>
338       <dd>Returns either the second child or the third child.  T can be any type except Void.  U
339         can be either Int32 or Int64.  If the first child is non-zero, returns the second child.
340         Otherwise returns the third child.</dd>
341
342       <dt>Int32 Load8Z(IntPtr, offset)</dt>
343       <dd>Loads a byte from the address, which is computed by adding the compile-time 32-bit
344         signed integer offset to the child value.  Zero extends the loaded byte, so the high 24
345         bits are all zero.  Must use the MemoryValue class.</dd>
346
347       <dt>Int32 Load8S(IntPtr, offset)</dt>
348       <dd>Loads a byte from the address, which is computed by adding the compile-time 32-bit
349         signed integer offset to the child value.  Sign extends the loaded byte.  Must use the
350         MemoryValue class.</dd>
351
352       <dt>Int32 Load16Z(IntPtr, offset)</dt>
353       <dd>Loads a 16-bit integer from the address, which is computed by adding the compile-time
354         32-bit signed integer offset to the child value.  Zero extends the loaded 16-bit
355         integer, so the high 16 bits are all zero.  Misaligned loads are not penalized.  Must
356         use the MemoryValue class.</dd>
357
358       <dt>Int32 Load16S(IntPtr, offset)</dt>
359       <dd>Loads a 16-bit integer from the address, which is computed by adding the compile-time
360         32-bit signed integer offset to the child value.  Sign extends the loaded 16-bit
361         integer.  Misaligned loads are not penalized.  Must use the MemoryValue class.</dd>
362
363       <dt>T Load(IntPtr, offset)</dt>
364       <dd>Valid for any type except Void.  Loads a value of that type from the address, which is
365         computed by adding the compile-time 32-bit signed integer offset to the child value.
366         Misaligned loads are not penalized.  Must use the MemoryValue class.</dd>
367
368       <dt>Void Store8(Int32, IntPtr, offset)</dt>
369       <dd>Stores a the low byte of the first child into the address computed by adding the
370         compile-time 32-bit signed integer offset to the second child.  Must use the MemoryValue
371         class.</dd>
372
373       <dt>Void Store16(Int32, IntPtr, offset)</dt>
374       <dd>Stores a the low 16 bits of the first child into the address computed by adding the
375         compile-time 32-bit signed integer offset to the second child.  Misaligned stores are
376         not penalized.  Must use the MemoryValue class.</dd>
377
378       <dt>Void Store(T, IntPtr, offset)</dt>
379       <dd>Stores the value in the first child into the address computed by adding the
380         compile-time 32-bit signed integer offset to the second child.  Misaligned stores are
381         not penalized.  Must use the MemoryValue class.</dd>
382
383       <dt>T1 CCall(IntPtr, [T2, [T3, ...]])</dt>
384       <dd>Performs a C function call to the function pointed to by the first child.  The types
385         that the function takes and the type that it returns are determined by the types of the
386         children and the type of the CCallValue.  Only the first child is mandatory.  Must use
387         the CCallValue class.</dd>
388
389       <dt>T1 Patchpoint([T2, [T3, ...]])</dt>
390       <dd>A Patchpoint is a customizable value.  Patchpoints take zero or more values of any
391         type and return any type.  A Patchpoint's behavior is determined by the generator
392         object.  The generator is a C++ lambda that gets called during code generation.  It gets
393         passed an assembler instance (specifically, CCallHelpers&) and an object describing
394         where to find all of the input values and where to put the result.  Here's an example:
395  
396         <pre><code>PatchpointValue* patchpoint = block->appendNew&lt;PatchpointValue&gt;(proc, Int32, Origin());
397 patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
398 patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
399 patchpoint->setGenerator(
400     [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
401         jit.add32(params[1].gpr(), params[2].gpr(), params[0].gpr());
402     });</code></pre>
403  
404         <p>This creates a patchpoint that just adds two numbers. The patchpoint is set to return
405           Int32.  The two child values, arg1 and arg2, are passed to the patchpoint with the
406           SomeRegister constraint, which just requests that they get put in appropriate
407           registers (GPR for integer values, FPR for floating point values).  The generator uses
408           the params object to figure out which registers the inputs are in (params[1] and
409           params[2]) and which register to put the result in (params[0]).  Many sophisticated
410           constraints are possible.  You can request that a child gets placed in a specific
411           register.  You can list additional registers that are
412           clobbered - either at the top of the patchpoint (i.e. early) so that the clobbered
413           registers interfere with the inputs, or at the bottom of the patchpoint (i.e. late) so
414           that the clobbered registers interfere with the output.  Patchpoint constraints also
415           allow you to force values onto the call argument area of the stack.  Patchpoints are
416           powerful enough to implement custom calling conventions, inline caches, and
417           side-exits.</p>
418
419         <p>A patchpoint is allowed to "side exit", i.e. abruptly exit from the procedure.  If it
420           wants to do so by returning, it can use Procedure's API for getting the callee-save
421           register layout, unwinding the callee-saves, and then returning.  More likely, the
422           patchpoint will take some exit state as part of its arguments, and it will manipulate
423           the call frame in place to make it look like another execution engine's call frame.
424           This is called OSR, and JavaScriptCore does it a lot.</p>
425  
426         <p>Must use the PatchpointValue class with the Patchpoint opcode.</p>
427       </dd>
428
429       <dt>T CheckAdd(T, T, [T2, [T3, ...]])</dt>
430       <dd>Checked integer addition.  Works for T = Int32 or T = Int64.  First first two children
431         are mandatory.  Additional children are optional.  All of the Check instructions take a
432         generator and value constraints like a Patchpoint.  In the case of a CheckAdd, the
433         generator runs on the path where the integer addition overflowed.  B3 assumes that
434         CheckAdd will side-exit upon overflow, so the generator must do some kind of
435         termination.  Usually, this is used to implement OSR exits on integer overflow and the
436         optional arguments to CheckAdd will be the OSR exit state.  Must use the CheckValue
437         class.</dd>
438
439       <dt>T CheckSub(T, T, [T2, [T3, ...]])</dt>
440       <dd>Checked integer subtraction.  Works for T = Int32 or T = Int64.  First first two
441         children are mandatory.  Additional children are optional.  All of the Check
442         instructions take a generator and value constraints like a Patchpoint.  In the case of a
443         CheckSub, the generator runs on the path where the integer subtraction overflowed.  B3
444         assumes that CheckSub will side-exit upon overflow, so the generator must do some kind
445         of termination.  Usually, this is used to implement OSR exits on integer overflow and
446         the optional arguments to CheckSub will be the OSR exit state.  You can use CheckSub for
447         checked negation by using zero for the first child.  B3 will select the native negate
448         instruction when you do this.  Must use the CheckValue class.</dd>
449
450       <dt>T CheckMul(T, T, [T2, [T3, ...]])</dt>
451       <dd>Checked integer multiplication.  Works for T = Int32 or T = Int64.  First first two
452         children are mandatory.  Additional children are optional.  All of the Check
453         instructions take a generator and value constraints like a Patchpoint.  In the case of a
454         CheckMul, the generator runs on the path where the integer multiplication overflowed.
455         B3 assumes that CheckMul will side-exit upon overflow, so the generator must do some
456         kind of termination.  Usually, this is used to implement OSR exits on integer overflow
457         and the optional arguments to CheckMul will be the OSR exit state.  Must use the
458         CheckValue class.</dd>
459
460       <dt>Void Check(T, [T2, [T3, ...]])</dt>
461       <dd>Exit check.  Works for T = Int32 or T = Int64.  This branches on the first child.  If
462         the first child is zero, this just falls through.  If it's non-zero, it goes to the exit
463         path generated by the passed generator.  Only the first child is mandatory.  B3 assumes
464         that Check will side-exit when the first child is non-zero, so the generator must do
465         some kind of termination.  Usually, this is used to implement OSR exit checks and the
466         optional arguments to Check will be the OSR exit state.  Check supports efficient
467         compare/branch fusion, so you can Check for fairly sophisticated predicates.  For
468         example, Check(Equal(LessThan(@a, @b), 0)) where @a and @b are doubles will be generated
469         to an instruction that branches to the exit if @a &gt;= @b or if either @a or @b are
470         NaN.  Must use the CheckValue class.</dd>
471
472       <dt>Void Upsilon(T, ^phi)</dt>
473       <dd>B3 uses SSA.  SSA requires that each variable gets assigned to only once anywhere in
474         the procedure.  But that doesn't work if you have a variable that is supposed to be the
475         result of merging two values along control flow.  B3 uses Phi values to represent value
476         merges, just like SSA compilers usually do.  But while other SSA compilers represent the
477         inputs to the Phi by listing the control flow edges from which the Phi gets its values,
478         B3 uses the Upsilon value.  Each Phi behaves as if it has a memory location associated
479         with it.  Executing the Phi behaves like a load from that memory location.
480         Upsilon(@value, ^phi) behaves like a store of @value into the memory location associated
481         with @phi.  We say "^phi" when we mean that we are writing to the memory location
482         associated with the Phi.  Must use the UpsilonValue class.</dd>
483
484       <dt>T Phi()</dt>
485       <dd>Works for any type except Void.  Represents a local memory location large enough to
486         hold T.  Loads from that memory location.  The only way to store to that location is
487         with Upsilon.</dd>
488
489       <dt>Void Jump(takenBlock)</dt>
490       <dd>Jumps to takenBlock.  This is a ControlValue, so it must appear at the end of the
491         basic block.</dd>
492
493       <dt>Void Branch(T, takenBlock, notTakenBlock)</dt>
494       <dd>Works for T = Int32 or T = Int64.  Branches on the child.  If the child is non-zero,
495         it branches to the takenBlock.  Otherwise it branches to the notTakenBlock.  Must use
496         the ControlValue class.  Must appear at the end of the basic block.</dd>
497
498       <dt>Void Switch(T, cases...)</dt>
499       <dd>Works for T = Int32 or T = Int64.  Switches on the child.  Contains a list of switch
500         cases.  Each switch case has an integer constant and a target block.  The switch value
501         also contains a fall-through target in case the child has a value that wasn't mentioned
502         in the cases list.  Must use the SwitchValue class.  Must appear at the end of the basic
503         block.</dd>
504
505       <dt>Void Return(T)</dt>
506       <dd>Works for any type except Void.  Returns the given value and terminates the procedure.
507         This is a ControlValue, but it must have an empty successors list.  Must appear at the
508         end of the basic block.</dd>
509
510       <dt>Void Oops()</dt>
511       <dd>Indicates unreachable code.  This may be implemented as either a trap or as a bare
512         fall-through, since B3 is allowed to assume that this will never be reached.  This is a
513         ControlValue, but it must have an empty successors list.  Must appear at the end of the
514         basic block.  Note that we also use the Oops opcode to mean "no such opcode" in some B3
515         transformations.</dd>
516     </dl>
517
518   </body>
519 </html>
520