@@ -585,6 +585,7 @@ EDDI::cloneInstr(Instruction &I,
585585 } // else place it right after the instruction we are working on
586586 else {
587587 IClone->insertAfter (&I);
588+ ClonedInstructions.insert (IClone);
588589 }
589590 DuplicatedInstructionMap.insert (
590591 std::pair<Instruction *, Instruction *>(&I, IClone));
@@ -1567,6 +1568,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) {
15671568
15681569 // list of duplicated instructions to remove since they are equal to the original
15691570 std::set<CallBase *> GrayAreaCallsToFix;
1571+ ClonedInstructions.clear ();
15701572 int iFn = 1 ;
15711573 LLVM_DEBUG (dbgs () << " Iterating over the functions...\n " );
15721574
@@ -2055,6 +2057,63 @@ void EDDI::fixGlobalCtors(Module &M) {
20552057 NewGlobalCtors->setSection (Section);
20562058}
20572059
2060+ /* *
2061+ * REPAIR groups all original instructions first, followed by all their
2062+ * duplicates, producing the coarse-grain order:
2063+ * A, B, C, A_dup, B_dup, C_dup
2064+ *
2065+ * This layout increases the temporal and spatial distance between a MI/SI
2066+ * pair. As a result, a single transient fault (SEU) is less likely to
2067+ * corrupt both the original and its duplicate before a consistency check
2068+ * can detect the mismatch (improving error-detection coverage for
2069+ * spatially-correlated faults)
2070+ *
2071+ * The function is called after the EDDI duplication phase has already
2072+ * cloned every eligible instruction and wired up operands. It only moves
2073+ * instructions;
2074+ *
2075+ * @param BB The basic block whose instructions are to be
2076+ * reordered
2077+ */
2078+ void EDDI::repairBasicBlock (BasicBlock &BB ) {
2079+
2080+ // Collect all duplicated instructions in this BB,
2081+ // preserving their relative order so that data-flow dependencies
2082+ // among duplicates remain satisfied after the move
2083+ std::vector<Instruction *> DupsInOrder;
2084+
2085+ for (Instruction &I : BB ) {
2086+ // PHINodes must stay at the top of the block (LLVM invariant).
2087+ // AllocaInsts are kept in the entry block's alloca region.
2088+ // Terminators (br, ret, switch, …) must remain last.
2089+ // None of these should be relocated
2090+
2091+ if (I.isTerminator () || isa<CallBase>(I)) {
2092+ // If there are no duplicates in this block, nothing to reorder
2093+ if (DupsInOrder.empty ())
2094+ return ;
2095+
2096+ // Move every duplicate just before the terminator, in their
2097+ // original relative order
2098+ for (Instruction *Dup : DupsInOrder) {
2099+ if (isa<PHINode>(Dup)){
2100+ Dup->moveBefore (BB .getFirstNonPHI ());
2101+ }
2102+ else {
2103+ Dup->moveBefore (&I);
2104+ }
2105+ }
2106+ DupsInOrder.clear ();
2107+ continue ;
2108+ } else if (ClonedInstructions.find (&I) != ClonedInstructions.end ()) {
2109+ // If this instruction belongs to the cloned set, it is a duplicate
2110+ // that needs to be sunk to the bottom of the block
2111+ DupsInOrder.push_back (&I);
2112+ }
2113+ }
2114+ }
2115+
2116+
20582117// -----------------------------------------------------------------------------
20592118// New PM Registration
20602119// -----------------------------------------------------------------------------
0 commit comments