From 561abe9cb60c21b6d7179f79cdfb877e82a80368 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 2 Apr 2024 12:45:08 -0400 Subject: [PATCH] ValueDominanceValidation: forbid crossblock liveness Now that we have successfully eliminated crossblock liveness from the IR we generate, validate as much to ensure it doesn't come back. We will take advantage of this new invariant in RA in the future. Signed-off-by: Alyssa Rosenzweig --- .../IR/Passes/ValueDominanceValidation.cpp | 108 ++++-------------- 1 file changed, 21 insertions(+), 87 deletions(-) diff --git a/FEXCore/Source/Interface/IR/Passes/ValueDominanceValidation.cpp b/FEXCore/Source/Interface/IR/Passes/ValueDominanceValidation.cpp index cd51e824d8..f40f878b24 100644 --- a/FEXCore/Source/Interface/IR/Passes/ValueDominanceValidation.cpp +++ b/FEXCore/Source/Interface/IR/Passes/ValueDominanceValidation.cpp @@ -106,95 +106,29 @@ bool ValueDominanceValidation::Run(IREmitter *IREmit) { OrderedNodeWrapper Arg = IROp->Args[i]; - // We must ensure domininance of all SSA arguments - if (Arg.ID() >= BlockIROp->Begin.ID() && - Arg.ID() < BlockIROp->Last.ID()) { - // If the SSA argument is defined INSIDE this block - // then it must only be declared prior to this instruction - // Eg: Valid - // CodeBlock_1: - // %_1 = Load - // %_2 = Load - // %_3 = %_1, %_2 - // - // Eg: Invalid - // CodeBlock_1: - // %_1 = Load - // %_2 = %_1, %_3 - // %_3 = Load - if (Arg.ID() > CodeID) { - HadError |= true; - Errors << "Inst %" << CodeID << ": Arg[" << i << "] %" << Arg.ID() << " definition does not dominate this use!" << std::endl; - } + // If the SSA argument is not defined INSIDE the block, we have + // cross-block liveness, which we forbid in the IR to simplify RA. + if (!(Arg.ID() >= BlockIROp->Begin.ID() && + Arg.ID() < BlockIROp->Last.ID())) { + HadError |= true; + Errors << "Inst %" << CodeID << ": Arg[" << i << "] %" << Arg.ID() << " definition not local!" << std::endl; + continue; } - else if (Arg.ID() < BlockIROp->Begin.ID()) { - // If the SSA argument is defined BEFORE this block - // then THIS block needs to be dominated by the flow of blocks up until this point - - // Eg: Valid - // CodeBlock_1: - // %_1 = Load - // %_2 = Load - // Jump %CodeBlock_2 - // - // CodeBlock_2: - // %_3 = %_1, %_2 - // - // Eg: Invalid - // CodeBlock_1: - // %_1 = Load - // %_2 = Load - // Jump %CodeBlock_3 - // - // CodeBlock_2: - // %_3 = %_1, %_2 - // - // CodeBlock_3: - // ... - - // We need to walk the predecessors to see if the value comes from there - fextl::set Predecessors { BlockNode }; - // Recursively gather all predecessors of BlockNode - for (auto NodeIt = Predecessors.begin(); NodeIt != Predecessors.end();) { - auto PredBlock = &OffsetToBlockMap.try_emplace(CurrentIR.GetID(*NodeIt)).first->second; - ++NodeIt; - - for (auto *Pred : PredBlock->Predecessors) { - if (Predecessors.insert(Pred).second) { - // New blocks added, so repeat from the beginning to pull in their predecessors - NodeIt = Predecessors.begin(); - } - } - } - - bool FoundPredDefine = false; - - for (auto* Pred : Predecessors) { - auto PredIROp = CurrentIR.GetOp(Pred); - if (Arg.ID() >= PredIROp->Begin.ID() && - Arg.ID() < PredIROp->Last.ID()) { - FoundPredDefine = true; - break; - } - Errors << "\tChecking Pred %" << CurrentIR.GetID(Pred) << std::endl; - } - - if (!FoundPredDefine) { - HadError |= true; - Errors << "Inst %" << CodeID << ": Arg[" << i << "] %" << Arg.ID() << " definition does not dominate this use! But was defined before this block!" << std::endl; - } - } - else if (Arg.ID() > BlockIROp->Last.ID()) { - // If this SSA argument is defined AFTER this block then it is just completely broken - // Eg: Invalid - // CodeBlock_1: - // %_1 = Load - // %_2 = %_1, %_3 - // Jump %CodeBlock_2 - // - // CodeBlock_2: - // %_3 = Load + // The SSA argument is defined INSIDE this block. + // It must only be declared prior to this instruction + // Eg: Valid + // CodeBlock_1: + // %_1 = Load + // %_2 = Load + // %_3 = %_1, %_2 + // + // Eg: Invalid + // CodeBlock_1: + // %_1 = Load + // %_2 = %_1, %_3 + // %_3 = Load + if (Arg.ID() > CodeID) { HadError |= true; Errors << "Inst %" << CodeID << ": Arg[" << i << "] %" << Arg.ID() << " definition does not dominate this use!" << std::endl; }