From 95e95f2fbf2578e434a33cfe77ab9708129b61f0 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Tue, 23 Apr 2024 10:29:22 +0100 Subject: [PATCH] Make serialising Yk IR instructions more flexible. Initially, each LLVM IR instruction had to be lowered to exactly one Yk IR instruction. Why? Because it was easy to implement. Later we realised we needed to skip certain LLVM instructions (e.g. debug calls). At this point we added complexity. Due to the way the deserialiser works, we need to emit an instruction count field before emitting the instructions themselves. Therefore we had to first count how many instructions would be emitted in an initial loop, emit this count, then emit the instructions themselves in a second loop. This change removes the need for the first loop by "patching up" a placeholder instruction count field once the number of instructions is known. In turn this simplifies the code quite a bit, making it easier to maintain, but also will make it easier for one LLVM instruction to be lowered to more than one Yk IR instruction. For example, we might opt to lower an LLVM switch instruction into a series of Yk IR conditional instructions. No functional change. No runtime changes required. --- llvm/lib/YkIR/YkIRWriter.cpp | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/llvm/lib/YkIR/YkIRWriter.cpp b/llvm/lib/YkIR/YkIRWriter.cpp index ecbdbfce612717..397f08ba67e20e 100644 --- a/llvm/lib/YkIR/YkIRWriter.cpp +++ b/llvm/lib/YkIR/YkIRWriter.cpp @@ -641,7 +641,6 @@ class YkIRWriter { void serialiseBlock(BasicBlock &BB, ValueLoweringMap &VLMap, unsigned &BBIdx) { - // Keep the instruction skipping logic in one place. auto ShouldSkipInstr = [](Instruction *I) { // Skip non-semantic instrucitons for now. // @@ -661,25 +660,15 @@ class YkIRWriter { return false; }; - // Count instructions. - // - // FIXME: I don't like this much: - // - // - Assumes one LLVM instruction becomes exactly one Yk IR instruction. - // - Requires a second loop to count ahead of time. + // num_instrs: // - // Can we emit the instrucitons into a temp buffer and keep a running count - // of how many instructions we generated instead? - size_t NumInstrs = 0; - for (Instruction &I : BB) { - if (ShouldSkipInstr(&I)) { - continue; - } - NumInstrs++; - } + // We don't know how many instructions there will be in advance, so what we + // do is emit a placeholder field (in the form of a symbol value) which is + // patched up (assigned) later. + MCContext &MCtxt = OutStreamer.getContext(); + MCSymbol *NumInstrsSym = MCtxt.createTempSymbol(); + OutStreamer.emitSymbolValue(NumInstrsSym, sizeof(size_t)); - // num_instrs: - OutStreamer.emitSizeT(NumInstrs); // instrs: unsigned InstIdx = 0; for (Instruction &I : BB) { @@ -689,8 +678,10 @@ class YkIRWriter { serialiseInst(&I, VLMap, BBIdx, InstIdx); } - // Check we emitted the number of instructions that we promised. - assert(InstIdx == NumInstrs); + // Now that we have finished serialising instructions, we know how many + // there are and we can patch up the "number of instructions" field. + OutStreamer.emitAssignment(NumInstrsSym, + MCConstantExpr::create(InstIdx, MCtxt)); BBIdx++; }