More precise handling of const/reassign in ssa form

Addressed a TODO from the previous PR. When we enter SSA form, when we rewrite 
variable reassignments we currently change the identifier but leave the kind of 
the lvalue alone; technically we should convert from Reassign to Const. After 
doing that, it's easier to correctly update when we leave SSA form, we can 
convert just a subset back into let/reassign (but leave most things alone as 
const).
This commit is contained in:
Joe Savona
2022-12-20 16:09:59 -08:00
parent 178bde3495
commit bc0787fefb
2 changed files with 13 additions and 12 deletions
+2
View File
@@ -3,6 +3,7 @@ import {
HIRFunction,
Identifier,
IdentifierId,
InstructionKind,
makeInstructionId,
makeType,
Phi,
@@ -202,6 +203,7 @@ export default function enterSSA(func: HIRFunction, env: Environment) {
newPlace = builder.getPlace(oldPlace);
} else {
newPlace = builder.definePlace(oldPlace);
instr.lvalue.kind = InstructionKind.Const;
}
instr.lvalue.place = newPlace;
}
+11 -12
View File
@@ -291,23 +291,22 @@ export function leaveSSA(fn: HIRFunction) {
// Finally, iterate the instructions and perform any rewrites as well as converting
// SSA variables to `const` where possible
for (const instr of block.instructions) {
const { lvalue, value } = instr;
const { lvalue } = instr;
if (lvalue !== null) {
rewritePlace(lvalue.place, rewrites);
if (
lvalue.kind !== InstructionKind.Const &&
lvalue.kind === InstructionKind.Const &&
lvalue.place.memberPath === null &&
!rewrites.has(lvalue.place.identifier) &&
(!reassignments.has(lvalue.place.identifier) ||
reassignments.get(lvalue.place.identifier) !==
lvalue.place.identifier)
rewrites.has(lvalue.place.identifier)
) {
// Convert individual SSA reassignments into const declarations
// otherwise the code would be invalid, since the SSA identifiers
// aren't otherwise declared.
// TODO @josephsavona: do this in EnterSSA instead?
lvalue.kind = InstructionKind.Const;
// For rewrites, the declaration of the canonical identifier has to be `let`,
// all other assignments are reassignments (which we annotate for codegen
// purposes).
lvalue.kind =
rewrites.get(lvalue.place.identifier) === lvalue.place.identifier
? InstructionKind.Let
: InstructionKind.Reassign;
}
rewritePlace(lvalue.place, rewrites);
}
for (const operand of eachInstructionValueOperand(instr.value)) {
rewritePlace(operand, rewrites);