mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[ssa] Use Identifier for updating SSA
Instead of using Place, use Identifier as the unit of comparison in SSA. Place is too high level and can not be substituted for other Places (even those with the same Identifier) as Place contain higher level metadata such as memberPath.
This commit is contained in:
@@ -166,8 +166,8 @@ export type InstructionValue = (InstructionData & { path: NodePath }) | Place;
|
||||
|
||||
export type Phi = {
|
||||
kind: "Phi";
|
||||
lvalue: LValue;
|
||||
operands: Map<BasicBlock, Place>;
|
||||
id: Identifier;
|
||||
operands: Map<BasicBlock, Identifier>;
|
||||
};
|
||||
|
||||
export type InstructionData =
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { assertExhaustive } from "../Common/utils";
|
||||
import {
|
||||
HIR,
|
||||
Identifier,
|
||||
Instruction,
|
||||
InstructionKind,
|
||||
InstructionValue,
|
||||
@@ -91,11 +92,11 @@ function printInstruction(instr: Instruction): string {
|
||||
|
||||
function printPhi(phi: Phi): string {
|
||||
const items = [];
|
||||
items.push(printLValue(phi.lvalue));
|
||||
items.push(printIdentifier(phi.id));
|
||||
items.push(": phi(");
|
||||
const phis = [];
|
||||
for (const [block, place] of phi.operands) {
|
||||
phis.push(`bb${block.id}: ${printPlace(place)}`);
|
||||
for (const [block, id] of phi.operands) {
|
||||
phis.push(`bb${block.id}: ${printIdentifier(id)}`);
|
||||
}
|
||||
|
||||
items.push(phis.join(", "));
|
||||
@@ -256,13 +257,7 @@ export function printLValue(lval: LValue): string {
|
||||
}
|
||||
|
||||
export function printPlace(place: Place): string {
|
||||
const items = [
|
||||
place.effect,
|
||||
" ",
|
||||
place.identifier.name,
|
||||
"$",
|
||||
place.identifier.id,
|
||||
];
|
||||
const items = [place.effect, " ", printIdentifier(place.identifier)];
|
||||
if (place.memberPath != null) {
|
||||
for (const path of place.memberPath) {
|
||||
items.push(".");
|
||||
@@ -271,3 +266,7 @@ export function printPlace(place: Place): string {
|
||||
}
|
||||
return items.filter((x) => x != null).join("");
|
||||
}
|
||||
|
||||
export function printIdentifier(id: Identifier): string {
|
||||
return `${id.name ?? ""}\$${id.id}`;
|
||||
}
|
||||
|
||||
@@ -3,24 +3,22 @@ import { assertExhaustive } from "../Common/utils";
|
||||
import {
|
||||
BasicBlock,
|
||||
BlockId,
|
||||
Effect,
|
||||
HIRFunction,
|
||||
IdentifierId,
|
||||
Identifier,
|
||||
Instruction,
|
||||
InstructionKind,
|
||||
Phi,
|
||||
Place,
|
||||
} from "./HIR";
|
||||
import { Environment } from "./HIRBuilder";
|
||||
import { printPlace } from "./PrintHIR";
|
||||
import { printIdentifier } from "./PrintHIR";
|
||||
|
||||
type IncompletePhi = {
|
||||
old: Place;
|
||||
new: Place;
|
||||
oldId: Identifier;
|
||||
newId: Identifier;
|
||||
};
|
||||
|
||||
type State = {
|
||||
defs: Map<IdentifierId, Place>;
|
||||
defs: Map<Identifier, Identifier>;
|
||||
incompletePhis: IncompletePhi[];
|
||||
};
|
||||
|
||||
@@ -48,99 +46,80 @@ class SSABuilder {
|
||||
return this.#states.get(this.#current)!;
|
||||
}
|
||||
|
||||
// This tries to reuse all existing information about the oldPlace in case there's
|
||||
// useful information from previous compiler passes.
|
||||
makePlace(oldPlace: Place): Place {
|
||||
const identifier = {
|
||||
...oldPlace.identifier,
|
||||
id: this.nextIdentifierId,
|
||||
};
|
||||
definePlace(oldPlace: Place): Place {
|
||||
const oldId = oldPlace.identifier;
|
||||
const newId = { ...oldId, id: this.nextIdentifierId };
|
||||
this.state().defs.set(oldId, newId);
|
||||
return {
|
||||
...oldPlace,
|
||||
identifier,
|
||||
identifier: newId,
|
||||
};
|
||||
}
|
||||
|
||||
makePlaceForPhi(oldPlace: Place): Place {
|
||||
const identifier = {
|
||||
...oldPlace.identifier,
|
||||
id: this.nextIdentifierId,
|
||||
};
|
||||
return {
|
||||
identifier,
|
||||
kind: "Identifier",
|
||||
memberPath: null,
|
||||
effect: Effect.Mutate,
|
||||
path: null as any,
|
||||
};
|
||||
}
|
||||
|
||||
definePlace(oldPlace: Place): Place {
|
||||
const newPlace = this.makePlace(oldPlace);
|
||||
this.state().defs.set(oldPlace.identifier.id, newPlace);
|
||||
return newPlace;
|
||||
}
|
||||
|
||||
getPlace(oldPlace: Place): Place {
|
||||
return this.getPlaceAt(oldPlace, this.#current!);
|
||||
const newId = this.getIdAt(oldPlace.identifier, this.#current!);
|
||||
return {
|
||||
...oldPlace,
|
||||
identifier: newId,
|
||||
};
|
||||
}
|
||||
|
||||
getPlaceAt(oldPlace: Place, block: BasicBlock): Place {
|
||||
getIdAt(oldId: Identifier, block: BasicBlock): Identifier {
|
||||
// check if Place is defined locally
|
||||
const state = this.#states.get(block)!;
|
||||
|
||||
if (state.defs.has(oldPlace.identifier.id)) {
|
||||
return state.defs.get(oldPlace.identifier.id)!;
|
||||
if (state.defs.has(oldId)) {
|
||||
return state.defs.get(oldId)!;
|
||||
}
|
||||
|
||||
if (block.preds.size == 0) {
|
||||
// We're at the entry block and haven't found our defintion yet.
|
||||
console.log(
|
||||
`Unable to find "${printPlace(oldPlace)}", assuming it's a global`
|
||||
`Unable to find "${printIdentifier(oldId)}", assuming it's a global`
|
||||
);
|
||||
//return oldPlace;
|
||||
return oldId;
|
||||
}
|
||||
|
||||
if (unsealedPreds.get(block)! > 0) {
|
||||
// We haven't visited all our predecessors, let's place an incomplete phi
|
||||
// for now.
|
||||
const newPlace = this.makePlaceForPhi(oldPlace);
|
||||
state.incompletePhis.push({ old: oldPlace, new: newPlace });
|
||||
state.defs.set(oldPlace.identifier.id, newPlace);
|
||||
return newPlace;
|
||||
const newId = { ...oldId, id: this.nextIdentifierId };
|
||||
state.incompletePhis.push({ oldId, newId });
|
||||
state.defs.set(oldId, newId);
|
||||
return newId;
|
||||
}
|
||||
|
||||
// Only one predecessor, let's check there
|
||||
if (block.preds.size == 1) {
|
||||
const [pred] = block.preds;
|
||||
const newPlace = this.getPlaceAt(oldPlace, pred);
|
||||
state.defs.set(oldPlace.identifier.id, newPlace);
|
||||
return newPlace;
|
||||
const newId = this.getIdAt(oldId, pred);
|
||||
state.defs.set(oldId, newId);
|
||||
return newId;
|
||||
}
|
||||
|
||||
// There are multiple predecessors, we need a phi.
|
||||
const newPlace = this.makePlaceForPhi(oldPlace);
|
||||
const newId = { ...oldId, id: this.nextIdentifierId };
|
||||
// Adding a phi may loop back to our block if there is a loop in the CFG. We
|
||||
// update our defs before adding the phi to terminate the recursion rather than
|
||||
// looping infinitely.
|
||||
state.defs.set(oldPlace.identifier.id, newPlace);
|
||||
this.addPhi(block, oldPlace, newPlace);
|
||||
state.defs.set(oldId, newId);
|
||||
this.addPhi(block, oldId, newId);
|
||||
|
||||
// TODO(gsn): Can we just return `newPlace` rather than looking it up?
|
||||
// `addPhi` _can_ mutate it, but _will_ it?
|
||||
return state.defs.get(oldPlace.identifier.id)!;
|
||||
return state.defs.get(oldId)!;
|
||||
}
|
||||
|
||||
addPhi(block: BasicBlock, oldPlace: Place, newPlace: Place) {
|
||||
const predDefs: Map<BasicBlock, Place> = new Map();
|
||||
addPhi(block: BasicBlock, oldId: Identifier, newId: Identifier) {
|
||||
const predDefs: Map<BasicBlock, Identifier> = new Map();
|
||||
for (const predBlock of block.preds) {
|
||||
const predPlace = this.getPlaceAt(oldPlace, predBlock);
|
||||
predDefs.set(predBlock, predPlace);
|
||||
const predId = this.getIdAt(oldId, predBlock);
|
||||
predDefs.set(predBlock, predId);
|
||||
}
|
||||
|
||||
const phi: Phi = {
|
||||
kind: "Phi",
|
||||
lvalue: { place: newPlace, kind: InstructionKind.Const },
|
||||
id: newId,
|
||||
operands: predDefs,
|
||||
};
|
||||
|
||||
@@ -150,7 +129,7 @@ class SSABuilder {
|
||||
fixIncompletePhis(block: BasicBlock) {
|
||||
const state = this.#states.get(block)!;
|
||||
for (const phi of state.incompletePhis) {
|
||||
this.addPhi(block, phi.old, phi.new);
|
||||
this.addPhi(block, phi.oldId, phi.newId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,14 +145,12 @@ class SSABuilder {
|
||||
const text = [];
|
||||
for (const [block, state] of this.#states) {
|
||||
text.push(`bb${block.id}:`);
|
||||
for (const [id, place] of state.defs) {
|
||||
text.push(` \$${id} = \$${place.identifier.id}`);
|
||||
for (const [oldId, newId] of state.defs) {
|
||||
text.push(` \$${oldId}: \$${newId}`);
|
||||
}
|
||||
|
||||
for (const incompletePhi of state.incompletePhis) {
|
||||
text.push(
|
||||
` iphi \$${incompletePhi.new.identifier} = \$${incompletePhi.old.identifier}`
|
||||
);
|
||||
text.push(` iphi \$${incompletePhi.newId} = \$${incompletePhi.oldId}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ function Component(props) {
|
||||
bb0:
|
||||
Const mutate a$5 = 1
|
||||
Const mutate b$6 = 2
|
||||
Const mutate x$7 = Array [mutate a$5, mutate b$6]
|
||||
Return mutate x$7
|
||||
Const mutate x$7 = Array [read a$5, read b$6]
|
||||
Return freeze x$7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -34,16 +34,15 @@ function foo$0() {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const mutate foo$11: phi()
|
||||
Const mutate a$9 = Array []
|
||||
Const mutate b$10 = Object { }
|
||||
Call mutate foo$11(mutate a$9, mutate b$10)
|
||||
Const mutate $12 = "div"
|
||||
Let mutate _$13 = JSX <mutate $12 a={mutate a$9} ></mutate $12>
|
||||
Call mutate foo$11(mutate b$10)
|
||||
Const mutate $14 = "div"
|
||||
Const mutate $15 = JSX <mutate $14 a={mutate a$9} b={mutate b$10} ></mutate $14>
|
||||
Return mutate $15
|
||||
Call mutate foo$4(mutate a$9, mutate b$10)
|
||||
Const mutate $11 = "div"
|
||||
Let mutate _$12 = JSX <read $11 a={freeze a$9} ></read $11>
|
||||
Call mutate foo$4(mutate b$10)
|
||||
Const mutate $13 = "div"
|
||||
Const mutate $14 = JSX <read $13 a={read a$9} b={freeze b$10} ></read $13>
|
||||
Return read $14
|
||||
```
|
||||
|
||||
## Code
|
||||
@@ -52,10 +51,10 @@ bb0:
|
||||
function Component$0(props$1) {
|
||||
const a$9 = [];
|
||||
const b$10 = {};
|
||||
foo$11(a$9, b$10);
|
||||
let _$13 = <div a={a$9}></div>;
|
||||
foo$4(a$9, b$10);
|
||||
let _$12 = <div a={a$9}></div>;
|
||||
|
||||
foo$11(b$10);
|
||||
foo$4(b$10);
|
||||
return <div a={a$9} b={b$10}></div>;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,27 +24,27 @@ bb0:
|
||||
Let mutate x$7 = 1
|
||||
Let mutate y$8 = 2
|
||||
Const mutate $9 = 2
|
||||
Const mutate $10 = Binary mutate y$8 === mutate $9
|
||||
If (mutate $10) then:bb2 else:bb1
|
||||
Const mutate $10 = Binary read y$8 === read $9
|
||||
If (read $10) then:bb2 else:bb1
|
||||
bb2:
|
||||
predecessor blocks: bb0
|
||||
Reassign mutate x$18 = 3
|
||||
Goto bb1
|
||||
bb1:
|
||||
predecessor blocks: bb0 bb2
|
||||
Const mutate y$12: phi(bb0: mutate y$8, bb2: mutate y$8)
|
||||
Const mutate x$17: phi(bb0: mutate x$7, bb2: mutate x$18)
|
||||
y$12: phi(bb0: y$8, bb2: y$8)
|
||||
x$17: phi(bb0: x$7, bb2: x$18)
|
||||
Const mutate $11 = 3
|
||||
Const mutate $13 = Binary mutate y$12 === mutate $11
|
||||
If (mutate $13) then:bb4 else:bb3
|
||||
Const mutate $13 = Binary read y$12 === read $11
|
||||
If (read $13) then:bb4 else:bb3
|
||||
bb4:
|
||||
predecessor blocks: bb1
|
||||
Reassign mutate x$16 = 5
|
||||
Goto bb3
|
||||
bb3:
|
||||
predecessor blocks: bb1 bb4
|
||||
Const mutate x$14: phi(bb1: mutate x$17, bb4: mutate x$16)
|
||||
Reassign mutate y$15 = mutate x$14
|
||||
x$14: phi(bb1: x$17, bb4: x$16)
|
||||
Reassign mutate y$15 = read x$14
|
||||
Return
|
||||
```
|
||||
|
||||
|
||||
@@ -21,16 +21,16 @@ bb0:
|
||||
Let mutate x$5 = 1
|
||||
Let mutate y$6 = 2
|
||||
Const mutate $7 = 2
|
||||
Const mutate $8 = Binary mutate y$6 === mutate $7
|
||||
If (mutate $8) then:bb2 else:bb1
|
||||
Const mutate $8 = Binary read y$6 === read $7
|
||||
If (read $8) then:bb2 else:bb1
|
||||
bb2:
|
||||
predecessor blocks: bb0
|
||||
Reassign mutate x$11 = 3
|
||||
Goto bb1
|
||||
bb1:
|
||||
predecessor blocks: bb0 bb2
|
||||
Const mutate x$9: phi(bb0: mutate x$5, bb2: mutate x$11)
|
||||
Reassign mutate y$10 = mutate x$9
|
||||
x$9: phi(bb0: x$5, bb2: x$11)
|
||||
Reassign mutate y$10 = read x$9
|
||||
Return
|
||||
```
|
||||
|
||||
|
||||
@@ -20,18 +20,18 @@ bb0:
|
||||
Goto bb1
|
||||
bb1:
|
||||
predecessor blocks: bb0 bb4
|
||||
Const mutate x$7: phi(bb0: mutate x$5, bb4: mutate x$10)
|
||||
x$7: phi(bb0: x$5, bb4: x$10)
|
||||
Const mutate $6 = 10
|
||||
Const mutate $8 = Binary mutate x$7 < mutate $6
|
||||
If (mutate $8) then:bb4 else:bb2
|
||||
Const mutate $8 = Binary read x$7 < read $6
|
||||
If (read $8) then:bb4 else:bb2
|
||||
bb4:
|
||||
predecessor blocks: bb1
|
||||
Const mutate $9 = 1
|
||||
Reassign mutate x$10 = Binary mutate x$7 + mutate $9
|
||||
Reassign mutate x$10 = Binary read x$7 + read $9
|
||||
Goto bb1
|
||||
bb2:
|
||||
predecessor blocks: bb1
|
||||
Return mutate x$7
|
||||
Return read x$7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -21,14 +21,14 @@ function foo() {
|
||||
bb0:
|
||||
Let mutate x$5 = 1
|
||||
Let mutate y$6 = 2
|
||||
If (mutate y$6) then:bb2 else:bb3
|
||||
If (read y$6) then:bb2 else:bb3
|
||||
bb2:
|
||||
predecessor blocks: bb0
|
||||
Let mutate z$8 = Binary mutate x$5 + mutate y$6
|
||||
Let mutate z$8 = Binary read x$5 + read y$6
|
||||
Goto bb1
|
||||
bb3:
|
||||
predecessor blocks: bb0
|
||||
Let mutate z$7 = mutate x$5
|
||||
Let mutate z$7 = read x$5
|
||||
Goto bb1
|
||||
bb1:
|
||||
predecessor blocks: bb3 bb2
|
||||
|
||||
@@ -32,11 +32,10 @@ function Foo$0() {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const mutate Foo$8: phi()
|
||||
Const mutate a$6 = Array []
|
||||
Const mutate b$7 = Object { }
|
||||
Let mutate c$9 = New mutate Foo$8(mutate a$6, mutate b$7)
|
||||
Return mutate c$9
|
||||
Let mutate c$8 = New mutate Foo$5(mutate a$6, mutate b$7)
|
||||
Return freeze c$8
|
||||
```
|
||||
|
||||
## Code
|
||||
@@ -45,8 +44,8 @@ bb0:
|
||||
function Component$0(props$1) {
|
||||
const a$6 = [];
|
||||
const b$7 = {};
|
||||
let c$9 = new Foo$8(a$6, b$7);
|
||||
return c$9;
|
||||
let c$8 = new Foo$5(a$6, b$7);
|
||||
return c$8;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -25,8 +25,8 @@ bb0:
|
||||
Let mutate x$6 = 1
|
||||
Let mutate y$7 = 2
|
||||
Const mutate $8 = 1
|
||||
Const mutate $9 = Binary mutate x$6 > mutate $8
|
||||
If (mutate $9) then:bb2 else:bb3
|
||||
Const mutate $9 = Binary read x$6 > read $8
|
||||
If (read $9) then:bb2 else:bb3
|
||||
bb2:
|
||||
predecessor blocks: bb0
|
||||
Reassign mutate x$14 = 2
|
||||
@@ -37,10 +37,10 @@ bb3:
|
||||
Goto bb1
|
||||
bb1:
|
||||
predecessor blocks: bb3 bb2
|
||||
Const mutate x$11: phi(bb3: mutate x$6, bb2: mutate x$14)
|
||||
Const mutate y$12: phi(bb3: mutate y$10, bb2: mutate y$7)
|
||||
Let mutate t$13 = Object { x: mutate x$11, y: mutate y$12 }
|
||||
Return mutate t$13
|
||||
x$11: phi(bb3: x$6, bb2: x$14)
|
||||
y$12: phi(bb3: y$10, bb2: y$7)
|
||||
Let mutate t$13 = Object { x: read x$11, y: read y$12 }
|
||||
Return freeze t$13
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -17,8 +17,8 @@ function Component(props) {
|
||||
bb0:
|
||||
Const mutate a$5 = 1
|
||||
Const mutate b$6 = 2
|
||||
Const mutate x$7 = Object { a: mutate a$5, b: mutate b$6 }
|
||||
Return mutate x$7
|
||||
Const mutate x$7 = Object { a: read a$5, b: read b$6 }
|
||||
Return freeze x$7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const x = [];
|
||||
const y = { x: x };
|
||||
y.x.push([]);
|
||||
return y;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const mutate x$4 = Array []
|
||||
Const mutate y$5 = Object { x: read x$4 }
|
||||
Const mutate $6 = Array []
|
||||
Call mutate y$5.x.push(mutate $6)
|
||||
Return freeze y$5
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function foo$0() {
|
||||
const x$4 = [];
|
||||
const y$5 = {
|
||||
x: x$4,
|
||||
};
|
||||
y$5.x.push([]);
|
||||
return y$5;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
function foo() {
|
||||
const x = [];
|
||||
const y = { x: x };
|
||||
y.x.push([]);
|
||||
return y;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function foo() {
|
||||
const x = [];
|
||||
const y = {};
|
||||
y.x = x;
|
||||
return y;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const mutate x$3 = Array []
|
||||
Const mutate y$4 = Object { }
|
||||
Reassign mutate y$5.x = read x$3
|
||||
Return freeze y$5
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function foo$0() {
|
||||
const x$3 = [];
|
||||
const y$4 = {};
|
||||
y$5 = x$3;
|
||||
return y$5;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
function foo() {
|
||||
const x = [];
|
||||
const y = {};
|
||||
y.x = x;
|
||||
return y;
|
||||
}
|
||||
@@ -19,16 +19,16 @@ function foo() {
|
||||
bb0:
|
||||
Let mutate x$4 = 1
|
||||
Const mutate $5 = 1
|
||||
Const mutate $6 = Binary mutate x$4 === mutate $5
|
||||
If (mutate $6) then:bb2 else:bb1
|
||||
Const mutate $6 = Binary read x$4 === read $5
|
||||
If (read $6) then:bb2 else:bb1
|
||||
bb2:
|
||||
predecessor blocks: bb0
|
||||
Reassign mutate x$8 = 2
|
||||
Goto bb1
|
||||
bb1:
|
||||
predecessor blocks: bb0 bb2
|
||||
Const mutate x$7: phi(bb0: mutate x$4, bb2: mutate x$8)
|
||||
Return mutate x$7
|
||||
x$7: phi(bb0: x$4, bb2: x$8)
|
||||
Return read x$7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -22,8 +22,8 @@ function foo() {
|
||||
bb0:
|
||||
Let mutate y$5 = 2
|
||||
Const mutate $6 = 1
|
||||
Const mutate $7 = Binary mutate y$5 > mutate $6
|
||||
If (mutate $7) then:bb2 else:bb3
|
||||
Const mutate $7 = Binary read y$5 > read $6
|
||||
If (read $7) then:bb2 else:bb3
|
||||
bb2:
|
||||
predecessor blocks: bb0
|
||||
Reassign mutate y$11 = 1
|
||||
@@ -34,8 +34,8 @@ bb3:
|
||||
Goto bb1
|
||||
bb1:
|
||||
predecessor blocks: bb3 bb2
|
||||
Const mutate y$9: phi(bb3: mutate y$8, bb2: mutate y$11)
|
||||
Let mutate x$10 = mutate y$9
|
||||
y$9: phi(bb3: y$8, bb2: y$11)
|
||||
Let mutate x$10 = read y$9
|
||||
Return
|
||||
```
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ function foo() {
|
||||
bb0:
|
||||
Let mutate x$4 = 1
|
||||
Let mutate y$5 = 2
|
||||
If (mutate y$5) then:bb2 else:bb1
|
||||
If (read y$5) then:bb2 else:bb1
|
||||
bb2:
|
||||
predecessor blocks: bb0
|
||||
Let mutate z$6 = Binary mutate x$4 + mutate y$5
|
||||
Let mutate z$6 = Binary read x$4 + read y$5
|
||||
Goto bb1
|
||||
bb1:
|
||||
predecessor blocks: bb0 bb2
|
||||
|
||||
@@ -30,32 +30,32 @@ function foo() {
|
||||
bb0:
|
||||
Let mutate x$10 = 1
|
||||
Const mutate $11 = 2
|
||||
Const mutate $12 = Binary mutate x$10 === mutate $11
|
||||
Const mutate $12 = Binary read x$10 === read $11
|
||||
Const mutate $13 = 1
|
||||
Const mutate $14 = Binary mutate x$10 === mutate $13
|
||||
Switch (mutate x$10)
|
||||
Case mutate $14: bb5
|
||||
Case mutate $12: bb3
|
||||
Const mutate $14 = Binary read x$10 === read $13
|
||||
Switch (<unknown> x$10)
|
||||
Case read $14: bb5
|
||||
Case read $12: bb3
|
||||
Default: bb2
|
||||
bb5:
|
||||
predecessor blocks: bb0
|
||||
Const mutate $21 = 1
|
||||
Reassign mutate x$22 = Binary mutate x$10 + mutate $21
|
||||
Reassign mutate x$22 = Binary read x$10 + read $21
|
||||
Goto bb1
|
||||
bb3:
|
||||
predecessor blocks: bb0
|
||||
Const mutate $19 = 2
|
||||
Reassign mutate x$20 = Binary mutate x$10 + mutate $19
|
||||
Reassign mutate x$20 = Binary read x$10 + read $19
|
||||
Goto bb1
|
||||
bb2:
|
||||
predecessor blocks: bb0
|
||||
Const mutate $15 = 3
|
||||
Reassign mutate x$16 = Binary mutate x$10 + mutate $15
|
||||
Reassign mutate x$16 = Binary read x$10 + read $15
|
||||
Goto bb1
|
||||
bb1:
|
||||
predecessor blocks: bb5 bb3 bb2
|
||||
Const mutate x$17: phi(bb5: mutate x$22, bb3: mutate x$20, bb2: mutate x$16)
|
||||
Let mutate y$18 = mutate x$17
|
||||
x$17: phi(bb5: x$22, bb3: x$20, bb2: x$16)
|
||||
Let mutate y$18 = read x$17
|
||||
Return
|
||||
```
|
||||
|
||||
|
||||
@@ -18,16 +18,16 @@ function foo() {
|
||||
bb0:
|
||||
Let mutate x$4 = 1
|
||||
Const mutate $5 = 1
|
||||
Const mutate $6 = Binary mutate x$4 === mutate $5
|
||||
If (mutate $6) then:bb2 else:bb1
|
||||
Const mutate $6 = Binary read x$4 === read $5
|
||||
If (read $6) then:bb2 else:bb1
|
||||
bb2:
|
||||
predecessor blocks: bb0
|
||||
Reassign mutate x$8 = 2
|
||||
Goto bb1
|
||||
bb1:
|
||||
predecessor blocks: bb0 bb2
|
||||
Const mutate x$7: phi(bb0: mutate x$4, bb2: mutate x$8)
|
||||
Throw mutate x$7
|
||||
x$7: phi(bb0: x$4, bb2: x$8)
|
||||
Throw read x$7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -21,18 +21,18 @@ bb0:
|
||||
Goto bb1
|
||||
bb1:
|
||||
predecessor blocks: bb0 bb3
|
||||
Const mutate x$7: phi(bb0: mutate x$5, bb3: mutate x$10)
|
||||
x$7: phi(bb0: x$5, bb3: x$10)
|
||||
Const mutate $6 = 10
|
||||
Const mutate $8 = Binary mutate x$7 < mutate $6
|
||||
If (mutate $8) then:bb3 else:bb2
|
||||
Const mutate $8 = Binary read x$7 < read $6
|
||||
If (read $8) then:bb3 else:bb2
|
||||
bb3:
|
||||
predecessor blocks: bb1
|
||||
Const mutate $9 = 1
|
||||
Reassign mutate x$10 = Binary mutate x$7 + mutate $9
|
||||
Reassign mutate x$10 = Binary read x$7 + read $9
|
||||
Goto bb1
|
||||
bb2:
|
||||
predecessor blocks: bb1
|
||||
Return mutate x$7
|
||||
Return read x$7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
Reference in New Issue
Block a user