mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Extract eachBlockOperand to its own visitor
Follow up for #757: - Adds a new visitor which iterates over every Place within a BasicBlock - Remove unused entryBlock binding - Comments
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
import { invariant } from "../CompilerError";
|
||||
import { HIRFunction, Identifier, Place } from "./HIR";
|
||||
import { eachInstructionOperand, eachTerminalOperand } from "./visitors";
|
||||
import { BasicBlock, HIRFunction, Identifier, Phi, Place } from "./HIR";
|
||||
import { eachBlockOperand } from "./visitors";
|
||||
|
||||
/**
|
||||
* Leaves SSA form by building up a mapping of SSA'd {@link Identifier}s to their original
|
||||
* {@link Identifier}, then rewriting all {@link Place}s within a {@link BasicBlock} to reference
|
||||
* the original id. This allows us to skip adding instruction copies when removing {@link Phi}s,
|
||||
* while still allowing shadowing to work.
|
||||
*/
|
||||
export default function leaveSSA(fn: HIRFunction) {
|
||||
const ir = fn.body;
|
||||
const entryBlock = ir.blocks.get(ir.entry);
|
||||
invariant(entryBlock, "expected to find the entry basic block");
|
||||
const originalIdMap = new Map<
|
||||
/* SSA'd id */ Identifier,
|
||||
/* original id*/ Identifier
|
||||
@@ -25,26 +28,12 @@ export default function leaveSSA(fn: HIRFunction) {
|
||||
return;
|
||||
}
|
||||
|
||||
function tryRewrite(place: Place) {
|
||||
const originalId = originalIdMap.get(place.identifier);
|
||||
if (originalId != null) {
|
||||
place.identifier = originalId;
|
||||
}
|
||||
}
|
||||
|
||||
for (const [, block] of ir.blocks) {
|
||||
for (const instr of block.instructions) {
|
||||
// LValues also need to be rewritten as they might be declaring or reassigning an identifier
|
||||
// that was previously SSA'd.
|
||||
if (instr.lvalue != null) {
|
||||
tryRewrite(instr.lvalue.place);
|
||||
for (const place of eachBlockOperand(block)) {
|
||||
const originalId = originalIdMap.get(place.identifier);
|
||||
if (originalId != null) {
|
||||
place.identifier = originalId;
|
||||
}
|
||||
for (const place of eachInstructionOperand(instr)) {
|
||||
tryRewrite(place);
|
||||
}
|
||||
}
|
||||
for (const place of eachTerminalOperand(block.terminal)) {
|
||||
tryRewrite(place);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
import { assertExhaustive } from "../Common/utils";
|
||||
import { BlockId, Instruction, Place, Terminal } from "./HIR";
|
||||
import { BasicBlock, BlockId, Instruction, Place, Terminal } from "./HIR";
|
||||
|
||||
export function* eachInstructionOperand(instr: Instruction): Iterable<Place> {
|
||||
const instrValue = instr.value;
|
||||
@@ -304,3 +304,16 @@ export function* eachTerminalOperand(terminal: Terminal): Iterable<Place> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over all {@link Place}s within a {@link BasicBlock}.
|
||||
*/
|
||||
export function* eachBlockOperand(block: BasicBlock): Iterable<Place> {
|
||||
for (const instr of block.instructions) {
|
||||
yield* eachInstructionOperand(instr);
|
||||
if (instr.lvalue != null) {
|
||||
yield instr.lvalue.place;
|
||||
}
|
||||
}
|
||||
yield* eachTerminalOperand(block.terminal);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user