43 Commits

Author SHA1 Message Date
ALEXks
fca6b15cba merged master 2025-05-27 19:00:57 +03:00
Egor Mayorov
00f205457c swap operators in AST 2025-05-27 15:55:02 +03:00
Egor Mayorov
59ce77c938 Use more complex algorythm for building new order of statements 2025-05-27 01:41:50 +03:00
Egor Mayorov
247a96b8ac update in new order 2025-05-24 23:15:30 +03:00
Egor Mayorov
ec28779d5b biulding new order 2025-05-24 19:56:15 +03:00
Egor Mayorov
8c0ee5a5ef some loop analysis done 2025-05-22 22:41:09 +03:00
Egor Mayorov
a8e65ccf26 Add _bin to gitignore 2025-05-19 22:23:36 +03:00
ALEXks
c1b1972d61 fixed 2025-05-19 21:21:13 +03:00
ALEXks
7ab4e7555a added json to SPF_GetArrayLinks 2025-05-19 21:21:13 +03:00
ALEXks
b59dcfffe1 fixed typo 2025-05-19 21:21:13 +03:00
ALEXks
563fd2d41a fixed AlignRuleBase::toJson() 2025-05-19 21:21:13 +03:00
ALEXks
96c1f8098b fixed Array::toJson() 2025-05-19 21:21:13 +03:00
ALEXks
4c85799c14 version updated 2025-05-19 21:21:13 +03:00
ALEXks
e278a1db91 added json for SPF_GetArrayDistribution pass 2025-05-19 21:21:13 +03:00
ALEXks
37d87dc645 added json for SPF_GetAllDeclaratedArrays pass 2025-05-19 21:21:13 +03:00
ALEXks
0f374ada8d fixed NULL error in matchParallelAndDist function 2025-05-19 21:21:13 +03:00
ALEXks
fb6e7eece6 fixed BUILD_INCLUDE_DEPENDENCIES pass 2025-05-19 21:21:13 +03:00
ALEXks
9e8a632cd6 updated submodule 2025-05-19 21:21:13 +03:00
ALEXks
abc23ecc38 fixed getNameInLocation 2025-05-19 21:21:13 +03:00
ALEXks
9ab4f8aba0 fixed module utils 2025-05-19 21:21:13 +03:00
ALEXks
fb93a5b1aa fixed gcov 2025-05-19 21:21:13 +03:00
ALEXks
d0b5558805 added json for SPF_GetGCovInfo pass 2025-05-19 21:21:13 +03:00
ALEXks
01b376a2bf fixed getInterfaceBlock 2025-05-19 21:21:13 +03:00
ALEXks
794e2daded fixed SPF_InsertIncludesPass unpacking 2025-05-19 21:21:13 +03:00
ALEXks
15d8a8dd8f added predictor library to Sapfor 2025-05-19 21:21:13 +03:00
f190c9ac48 added predictor library to submodule 2025-05-19 21:21:13 +03:00
ALEXks
38a51d7ad1 fixed predictor 2025-05-19 21:21:13 +03:00
ALEXks
c3a08e0c64 added json for line info 2025-05-19 21:21:13 +03:00
ALEXks
11cc671416 fixed dumping statistics 2025-05-19 21:21:13 +03:00
ALEXks
d9bf9eeb8e added pass dependency for RENAME_INLCUDES 2025-05-19 21:21:13 +03:00
ALEXks
264649d748 moved SPF_GetIncludeDependencies to json 2025-05-19 21:21:13 +03:00
ALEXks
731816035f added json for call graph positions, removed SPF_GetGraphVizOfFunctions 2025-05-19 21:21:13 +03:00
ALEXks
50c80f7ea1 added json for call graph 2025-05-19 21:21:13 +03:00
ALEXks
8e90d2517d removed checking from predictor 2025-05-19 21:21:13 +03:00
ALEXks
c4f20df7fc fixed 2025-05-19 21:21:13 +03:00
ALEXks
5f6bcdf974 version 2025-05-19 21:21:13 +03:00
ALEXks
7236f5bdf0 declare for module in progess 2025-05-19 21:21:13 +03:00
ALEXks
c8961828bc moved LoopGraph to json 2025-05-19 21:21:13 +03:00
ALEXks
c808e47805 moved LoopGraph to json 2025-05-19 21:21:13 +03:00
Egor Mayorov
600094f13a Some actions simplify analyzing IR 2025-05-13 00:47:25 +03:00
Egor Mayorov
5052e7e218 Pass with output file added 2025-04-15 18:10:13 +03:00
Egor Mayorov
d78c86a7dc change pass deps 2025-03-29 15:41:58 +03:00
Egor Mayorov
83c07da3cc New pass 2025-03-25 15:20:13 +03:00
7 changed files with 379 additions and 2 deletions

1
.gitignore vendored
View File

@@ -77,3 +77,4 @@ Sapfor/Sapc++/x64/
Sapfor/out/ Sapfor/out/
Sapfor/_bin/* Sapfor/_bin/*
_bin/*

View File

@@ -182,6 +182,8 @@ set(TR_IMPLICIT_NONE src/Transformations/set_implicit_none.cpp
src/Transformations/set_implicit_none.h) src/Transformations/set_implicit_none.h)
set(TR_REPLACE_ARRAYS_IN_IO src/Transformations/replace_dist_arrays_in_io.cpp set(TR_REPLACE_ARRAYS_IN_IO src/Transformations/replace_dist_arrays_in_io.cpp
src/Transformations/replace_dist_arrays_in_io.h) src/Transformations/replace_dist_arrays_in_io.h)
SET(SWAP_OPERATORS src/SwapOperators/swapOperators.cpp
src/SwapOperators/swapOperators.h)
set(TRANSFORMS set(TRANSFORMS
${TR_DEAD_CODE} ${TR_DEAD_CODE}
@@ -420,7 +422,8 @@ set(SOURCE_EXE
${ZLIB} ${ZLIB}
${GR_LAYOUT} ${GR_LAYOUT}
${PR_PARAM} ${PR_PARAM}
${PROJ_MAN}) ${PROJ_MAN}
${SWAP_OPERATORS})
add_executable(Sapfor_F ${SOURCE_EXE}) add_executable(Sapfor_F ${SOURCE_EXE})
source_group (CFGraph FILES ${CFG}) source_group (CFGraph FILES ${CFG})
@@ -464,6 +467,7 @@ source_group (Utils FILES ${UTILS})
source_group (VerificationCode FILES ${VERIF}) source_group (VerificationCode FILES ${VERIF})
source_group (ProjectParameters FILES ${PR_PARAM}) source_group (ProjectParameters FILES ${PR_PARAM})
source_group (ProjectManipulation FILES ${PROJ_MAN}) source_group (ProjectManipulation FILES ${PROJ_MAN})
source_group (SwapOperators FILES ${SWAP_OPERATORS})
source_group (VisualizerCalls FILES ${VS_CALLS}) source_group (VisualizerCalls FILES ${VS_CALLS})
source_group (VisualizerCalls\\GraphLayout FILES ${GR_LAYOUT}) source_group (VisualizerCalls\\GraphLayout FILES ${GR_LAYOUT})

View File

@@ -71,6 +71,8 @@
#include "VisualizerCalls/SendMessage.h" #include "VisualizerCalls/SendMessage.h"
#include "VisualizerCalls/BuildGraph.h" #include "VisualizerCalls/BuildGraph.h"
#include "SwapOperators/swapOperators.h"
#include "Transformations/enddo_loop_converter.h" #include "Transformations/enddo_loop_converter.h"
#include "Transformations/loop_transform.h" #include "Transformations/loop_transform.h"
#include "Transformations/array_assign_to_loop.h" #include "Transformations/array_assign_to_loop.h"
@@ -948,6 +950,10 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne
internalExit = err; internalExit = err;
} }
} }
else if (curr_regime == SWAP_OPERATORS)
{
runSwapOperators(file, loopGraph, fullIR, countOfTransform);
}
else if (curr_regime == PRIVATE_REMOVING_ANALYSIS) else if (curr_regime == PRIVATE_REMOVING_ANALYSIS)
{ {
auto itFound = loopGraph.find(file->filename()); auto itFound = loopGraph.find(file->filename());
@@ -1044,7 +1050,8 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne
PRIVATE_REMOVING, PRIVATE_REMOVING,
PRIVATE_ARRAYS_EXPANSION, PRIVATE_ARRAYS_EXPANSION,
PRIVATE_ARRAYS_SHRINKING, PRIVATE_ARRAYS_SHRINKING,
REMOVE_DEAD_CODE }; REMOVE_DEAD_CODE,
SWAP_OPERATORS };
if ((countOfTransform == 0 || internalExit > 0) && applyFor.find(curr_regime) != applyFor.end()) if ((countOfTransform == 0 || internalExit > 0) && applyFor.find(curr_regime) != applyFor.end())
{ {
@@ -2338,6 +2345,7 @@ void runPass(const int curr_regime, const char *proj_name, const char *folderNam
case INSERT_NO_DISTR_FLAGS_FROM_GUI: case INSERT_NO_DISTR_FLAGS_FROM_GUI:
case PRIVATE_REMOVING: case PRIVATE_REMOVING:
case RENAME_INLCUDES: case RENAME_INLCUDES:
case SWAP_OPERATORS:
runAnalysis(*project, curr_regime, true, "", folderName); runAnalysis(*project, curr_regime, true, "", folderName);
break; break;
case INLINE_PROCEDURES: case INLINE_PROCEDURES:

View File

@@ -122,6 +122,8 @@ enum passes {
CREATE_INTER_TREE, CREATE_INTER_TREE,
INSERT_INTER_TREE, INSERT_INTER_TREE,
SWAP_OPERATORS,
SHADOW_GROUPING, SHADOW_GROUPING,
INLINE_PROCEDURES, INLINE_PROCEDURES,
FILL_PARALLEL_REG_IR, FILL_PARALLEL_REG_IR,
@@ -315,6 +317,7 @@ static void setPassValues()
passNames[CHECK_PAR_REG_DIR] = "CHECK_PAR_REG_DIR"; passNames[CHECK_PAR_REG_DIR] = "CHECK_PAR_REG_DIR";
passNames[CREATE_INTER_TREE] = "CREATE_INTER_TREE"; passNames[CREATE_INTER_TREE] = "CREATE_INTER_TREE";
passNames[INSERT_INTER_TREE] = "INSERT_INTER_TREE"; passNames[INSERT_INTER_TREE] = "INSERT_INTER_TREE";
passNames[SWAP_OPERATORS] = "SWAP_OPERATORS";
passNames[CREATE_PARALLEL_REGIONS] = "CREATE_PARALLEL_REGIONS"; passNames[CREATE_PARALLEL_REGIONS] = "CREATE_PARALLEL_REGIONS";
passNames[PRIVATE_REMOVING_ANALYSIS] = "PRIVATE_REMOVING_ANALYSIS"; passNames[PRIVATE_REMOVING_ANALYSIS] = "PRIVATE_REMOVING_ANALYSIS";
passNames[PRIVATE_REMOVING] = "PRIVATE_REMOVING"; passNames[PRIVATE_REMOVING] = "PRIVATE_REMOVING";

View File

@@ -0,0 +1,353 @@
#include <map>
#include <unordered_set>
#include <vector>
#include <queue>
#include <iostream>
#include "../Utils/errors.h"
#include "../Utils/SgUtils.h"
#include "../GraphCall/graph_calls.h"
#include "../GraphCall/graph_calls_func.h"
#include "../CFGraph/CFGraph.h"
#include "../CFGraph/IR.h"
#include "../GraphLoop/graph_loops.h"
#include "swapOperators.h"
using namespace std;
unordered_set<int> loop_tags = {FOR_NODE/*, FORALL_NODE, WHILE_NODE, DO_WHILE_NODE*/};
unordered_set<int> importantDepsTags = {FOR_NODE, IF_NODE};
unordered_set<int> importantUpdDepsTags = {ELSEIF_NODE};
unordered_set<int> importantEndTags = {CONTROL_END};
vector<SAPFOR::IR_Block*> findInstructionsFromOperator(SgStatement* st, vector<SAPFOR::BasicBlock*> Blocks)
{
vector<SAPFOR::IR_Block*> result;
string filename = st -> fileName();
for (auto& block: Blocks)
{
vector<SAPFOR::IR_Block*> instructionsInBlock = block -> getInstructions();
for (auto& instruction: instructionsInBlock)
{
SgStatement* curOperator = instruction -> getInstruction() -> getOperator();
if (curOperator -> lineNumber() == st -> lineNumber())
result.push_back(instruction);
}
}
return result;
}
vector<SAPFOR::BasicBlock*> findFuncBlocksByFuncStatement(SgStatement *st, map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& FullIR)
{
vector<SAPFOR::BasicBlock*> result;
Statement* forSt = (Statement*)st;
for (auto& func: FullIR)
{
if (func.first -> funcPointer -> getCurrProcessFile() == forSt -> getCurrProcessFile()
&& func.first -> funcPointer -> lineNumber() == forSt -> lineNumber())
result = func.second;
}
return result;
}
map<SgForStmt*, vector<SAPFOR::BasicBlock*>> findAndAnalyzeLoops(SgStatement *st, vector<SAPFOR::BasicBlock*> blocks)
{
map<SgForStmt*, vector<SAPFOR::BasicBlock*>> result;
SgStatement *lastNode = st->lastNodeOfStmt();
while (st && st != lastNode)
{
if (loop_tags.find(st -> variant()) != loop_tags.end())
{
// part with find statements of loop
SgForStmt *forSt = (SgForStmt*)st;
SgStatement *loopBody = forSt -> body();
SgStatement *lastLoopNode = st->lastNodeOfStmt();
// part with find blocks and instructions of loops
unordered_set<int> blocks_nums;
while (loopBody && loopBody != lastLoopNode)
{
SAPFOR::IR_Block* IR = findInstructionsFromOperator(loopBody, blocks).front();
if (blocks_nums.find(IR -> getBasicBlock() -> getNumber()) == blocks_nums.end())
{
result[forSt].push_back(IR -> getBasicBlock());
blocks_nums.insert(IR -> getBasicBlock() -> getNumber());
}
loopBody = loopBody -> lexNext();
}
std::sort(result[forSt].begin(), result[forSt].end());
}
st = st -> lexNext();
}
return result;
}
map<SgStatement*, set<SgStatement*>> AnalyzeLoopAndFindDeps(SgForStmt* forStatement, vector<SAPFOR::BasicBlock*> loopBlocks, map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& FullIR)
{
map<SgStatement*, set<SgStatement*>> result;
for (SAPFOR::BasicBlock* bb: loopBlocks)
{
map<SAPFOR::Argument*, set<int>> blockReachingDefinitions = bb -> getRD_In();
vector<SAPFOR::IR_Block*> instructions = bb -> getInstructions();
for (SAPFOR::IR_Block* irBlock: instructions)
{
// TODO: Think about what to do with function calls and array references. Because there are also dependencies there that are not reflected in RD, but they must be taken into account
SAPFOR::Instruction* instr = irBlock -> getInstruction();
result[instr -> getOperator()];
// take Argument 1 and it's RD and push operators to final set
if (instr -> getArg1() != NULL)
{
SAPFOR::Argument* arg = instr -> getArg1();
set<int> prevInstructionsNumbers = blockReachingDefinitions[arg];
for (int i: prevInstructionsNumbers)
{
SAPFOR::Instruction* foundInstruction = getInstructionAndBlockByNumber(FullIR, i).first;
if (foundInstruction != NULL)
{
SgStatement* prevOp = foundInstruction -> getOperator();
if (prevOp != forStatement && instr -> getOperator() != forStatement && instr -> getOperator() -> lineNumber() > prevOp -> lineNumber()
&& prevOp -> lineNumber() > forStatement -> lineNumber())
result[instr -> getOperator()].insert(prevOp);
}
}
}
// take Argument 2 (if exists) and it's RD and push operators to final set
if (instr -> getArg2() != NULL)
{
SAPFOR::Argument* arg = instr -> getArg2();
set<int> prevInstructionsNumbers = blockReachingDefinitions[arg];
for (int i: prevInstructionsNumbers)
{
SAPFOR::Instruction* foundInstruction = getInstructionAndBlockByNumber(FullIR, i).first;
if (foundInstruction != NULL)
{
SgStatement* prevOp = foundInstruction -> getOperator();
if (prevOp != forStatement && instr -> getOperator() != forStatement&& instr -> getOperator() -> lineNumber() > prevOp -> lineNumber()
&& prevOp -> lineNumber() > forStatement -> lineNumber())
result[instr -> getOperator()].insert(prevOp);
}
}
}
// update RD
if (instr -> getResult() != NULL)
blockReachingDefinitions[instr -> getResult()] = {instr -> getNumber()};
}
}
return result;
}
void buildAdditionalDeps(SgForStmt* forStatement, map<SgStatement*, set<SgStatement*>>& dependencies)
{
SgStatement* lastNode = forStatement->lastNodeOfStmt();
vector<SgStatement*> importantDeps;
SgStatement* st = (SgStatement*) forStatement;
st = st -> lexNext();
SgStatement* logIfOp = NULL;
while (st && st != lastNode)
{
if(importantDeps.size() != 0)
{
if (st != importantDeps.back())
{
dependencies[st].insert(importantDeps.back());
}
}
if (logIfOp != NULL)
{
dependencies[st].insert(logIfOp);
logIfOp = NULL;
}
if (st -> variant() == LOGIF_NODE)
{
logIfOp = st;
}
if (importantDepsTags.find(st -> variant()) != importantDepsTags.end())
{
importantDeps.push_back(st);
}
if (importantUpdDepsTags.find(st -> variant()) != importantUpdDepsTags.end())
{
importantDeps.pop_back();
importantDeps.push_back(st);
}
if (importantEndTags.find(st -> variant()) != importantEndTags.end())
{
if(importantDeps.size() != 0)
{
importantDeps.pop_back();
}
}
st = st -> lexNext();
}
}
struct ReadyOp {
SgStatement* stmt;
int degree;
size_t arrival;
ReadyOp(SgStatement* s, int d, size_t a): stmt(s), degree(d), arrival(a) {}
};
struct ReadyOpCompare {
bool operator()(const ReadyOp& a, const ReadyOp& b) const {
if (a.degree != b.degree)
return a.degree > b.degree;
else
return a.arrival > b.arrival;
}
};
vector<SgStatement*> scheduleOperations(const map<SgStatement*, set<SgStatement*>>& dependencies)
{
// get all statements
unordered_set<SgStatement*> allStmtsSet;
for (const auto& pair : dependencies)
{
allStmtsSet.insert(pair.first);
for (SgStatement* dep : pair.second)
{
allStmtsSet.insert(dep);
}
}
vector<SgStatement*> allStmts(allStmtsSet.begin(), allStmtsSet.end());
// count deps and build reversed graph
unordered_map<SgStatement*, vector<SgStatement*>> graph;
unordered_map<SgStatement*, int> inDegree;
unordered_map<SgStatement*, int> degree;
for (auto op : allStmts)
inDegree[op] = 0;
// find and remember initial dependencies
unordered_set<SgStatement*> dependentStmts;
for (const auto& pair : dependencies)
{
SgStatement* op = pair.first;
const auto& deps = pair.second;
degree[op] = deps.size();
inDegree[op] = deps.size();
if (!deps.empty())
dependentStmts.insert(op);
for (auto dep : deps)
graph[dep].push_back(op);
}
for (SgStatement* op : allStmts)
{
if (!degree.count(op))
{
degree[op] = 0;
}
}
// build queues
using PQ = priority_queue<ReadyOp, vector<ReadyOp>, ReadyOpCompare>;
PQ readyDependent;
queue<SgStatement*> readyIndependent;
size_t arrivalCounter = 0;
for (auto op : allStmts)
{
if (inDegree[op] == 0)
{
if (dependentStmts.count(op))
{
readyDependent.emplace(op, degree[op], arrivalCounter++);
}
else
{
readyIndependent.push(op);
}
}
}
// main sort algorythm
vector<SgStatement*> executionOrder;
while (!readyDependent.empty() || !readyIndependent.empty())
{
SgStatement* current = nullptr;
if (!readyDependent.empty())
{
current = readyDependent.top().stmt;
readyDependent.pop();
}
else
{
current = readyIndependent.front();
readyIndependent.pop();
}
executionOrder.push_back(current);
for (SgStatement* neighbor : graph[current])
{
inDegree[neighbor]--;
if (inDegree[neighbor] == 0) {
if (dependentStmts.count(neighbor))
{
readyDependent.emplace(neighbor, degree[neighbor], arrivalCounter++);
}
else
{
readyIndependent.push(neighbor);
}
}
}
}
return executionOrder;
}
void buildNewAST(SgStatement* loop, vector<SgStatement*>& newBody)
{
SgStatement* endDo = loop->lastNodeOfStmt();
SgStatement* st = loop;
int lineNum = loop -> lineNumber() + 1;
for (int i = 0; i < newBody.size(); i++)
{
st -> setLexNext(*newBody[i]);
st = st -> lexNext();
st -> setlineNumber(lineNum);
lineNum++;
}
st -> setLexNext(*endDo);
}
void runSwapOperators(SgFile *file, std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& FullIR, int& countOfTransform)
{
std::cout << "SWAP_OPERATORS Pass" << std::endl; // to remove
countOfTransform += 1; // to remove
const int funcNum = file -> numberOfFunctions();
for (int i = 0; i < funcNum; ++i)
{
SgStatement *st = file -> functions(i);
vector<SAPFOR::BasicBlock*> blocks = findFuncBlocksByFuncStatement(st, FullIR);
map<SgForStmt*, vector<SAPFOR::BasicBlock*>> loopsMapping = findAndAnalyzeLoops(st, blocks);
for (pair<SgForStmt*, vector<SAPFOR::BasicBlock*>> loopForAnalyze: loopsMapping)
{
map<SgStatement*, set<SgStatement*>> dependencyGraph = AnalyzeLoopAndFindDeps(loopForAnalyze.first, loopForAnalyze.second, FullIR);
// TODO: Write a function that will go through the operators and update all dependencies so that there are no mix-ups and splits inside the semantic blocks (for if, do and may be some other cases)
buildAdditionalDeps(loopForAnalyze.first, dependencyGraph);
cout << endl;
int firstLine = loopForAnalyze.first -> lineNumber();
int lastLine = loopForAnalyze.first -> lastNodeOfStmt() -> lineNumber();
cout << "LOOP ANALYZE FROM " << firstLine << " TO " << lastLine << " RES" << endl;
// for (auto &v: dependencyGraph) {
// cout << "OPERATOR: " << v.first -> lineNumber() << " " << v.first -> variant() << "\nDEPENDS ON:" << endl;
// if (v.second.size() != 0)
// for (auto vv: v.second)
// cout << vv -> lineNumber() << " ";
// cout << endl;
// }
vector<SgStatement*> new_order = scheduleOperations(dependencyGraph);
cout << "RESULT ORDER:" << endl;
for (auto v: new_order)
if (v -> lineNumber() > firstLine)
cout << v -> lineNumber() << endl;
buildNewAST(loopForAnalyze.first, new_order);
st = loopForAnalyze.first -> lexNext();
while (st != loopForAnalyze.first -> lastNodeOfStmt())
{
cout << st -> lineNumber() << " " << st -> sunparse() << endl;
st = st -> lexNext();
}
}
}
return;
};

View File

@@ -0,0 +1,6 @@
#pragma once
#include "../GraphLoop/graph_loops.h"
#include "../CFGraph/CFGraph.h"
void runSwapOperators(SgFile *file, std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& FullIR, int& countOfTransform);

View File

@@ -212,6 +212,8 @@ void InitPassesDependencies(map<passes, vector<passes>> &passDepsIn, set<passes>
Pass(BUILD_IR) <= Pass(SUBST_EXPR_RD) <= Pass(SUBST_EXPR_RD_AND_UNPARSE); Pass(BUILD_IR) <= Pass(SUBST_EXPR_RD) <= Pass(SUBST_EXPR_RD_AND_UNPARSE);
list({BUILD_IR, CALL_GRAPH2}) <= Pass(SWAP_OPERATORS);
list({ LOOP_ANALYZER_DATA_DIST_S1, SUBST_EXPR_RD } ) <= Pass(PRIVATE_REMOVING_ANALYSIS); list({ LOOP_ANALYZER_DATA_DIST_S1, SUBST_EXPR_RD } ) <= Pass(PRIVATE_REMOVING_ANALYSIS);
list({ PRIVATE_REMOVING_ANALYSIS, REVERT_SUBST_EXPR_RD }) <= Pass(PRIVATE_REMOVING); list({ PRIVATE_REMOVING_ANALYSIS, REVERT_SUBST_EXPR_RD }) <= Pass(PRIVATE_REMOVING);