2025-03-25 15:18:49 +03:00
# include <map>
# include <unordered_set>
# include <vector>
# include <queue>
# include <iostream>
2025-05-13 00:46:32 +03:00
# 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"
2025-03-25 15:18:49 +03:00
# include "swapOperators.h"
2025-05-13 00:46:32 +03:00
using namespace std ;
2025-03-25 15:18:49 +03:00
2025-05-13 00:46:32 +03:00
unordered_set < int > loop_tags = { FOR_NODE /*, FORALL_NODE, WHILE_NODE, DO_WHILE_NODE*/ } ;
2025-05-27 01:41:50 +03:00
unordered_set < int > importantDepsTags = { FOR_NODE , IF_NODE } ;
unordered_set < int > importantUpdDepsTags = { ELSEIF_NODE } ;
2025-05-24 23:15:30 +03:00
unordered_set < int > importantEndTags = { CONTROL_END } ;
2025-05-13 00:46:32 +03:00
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 ;
}
2025-05-27 01:41:50 +03:00
vector < SAPFOR : : BasicBlock * > findFuncBlocksByFuncStatement ( SgStatement * st , map < FuncInfo * , vector < SAPFOR : : BasicBlock * > > & FullIR )
2025-05-13 00:46:32 +03:00
{
vector < SAPFOR : : BasicBlock * > result ;
Statement * forSt = ( Statement * ) st ;
2025-05-27 15:55:02 +03:00
for ( auto & func : FullIR )
2025-05-13 00:46:32 +03:00
{
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 )
2025-03-25 15:18:49 +03:00
{
2025-05-13 00:46:32 +03:00
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
2025-05-22 22:41:09 +03:00
unordered_set < int > blocks_nums ;
2025-05-13 00:46:32 +03:00
while ( loopBody & & loopBody ! = lastLoopNode )
{
SAPFOR : : IR_Block * IR = findInstructionsFromOperator ( loopBody , blocks ) . front ( ) ;
2025-05-22 22:41:09 +03:00
if ( blocks_nums . find ( IR - > getBasicBlock ( ) - > getNumber ( ) ) = = blocks_nums . end ( ) )
{
result [ forSt ] . push_back ( IR - > getBasicBlock ( ) ) ;
blocks_nums . insert ( IR - > getBasicBlock ( ) - > getNumber ( ) ) ;
}
2025-05-13 00:46:32 +03:00
loopBody = loopBody - > lexNext ( ) ;
}
2025-05-22 22:41:09 +03:00
std : : sort ( result [ forSt ] . begin ( ) , result [ forSt ] . end ( ) ) ;
2025-05-13 00:46:32 +03:00
}
st = st - > lexNext ( ) ;
}
return result ;
}
2025-05-24 19:56:15 +03:00
map < SgStatement * , set < SgStatement * > > AnalyzeLoopAndFindDeps ( SgForStmt * forStatement , vector < SAPFOR : : BasicBlock * > loopBlocks , map < FuncInfo * , vector < SAPFOR : : BasicBlock * > > & FullIR )
2025-05-13 00:46:32 +03:00
{
2025-05-24 19:56:15 +03:00
map < SgStatement * , set < SgStatement * > > result ;
2025-05-27 15:55:02 +03:00
for ( SAPFOR : : BasicBlock * bb : loopBlocks )
{
2025-05-27 01:41:50 +03:00
map < SAPFOR : : Argument * , set < int > > blockReachingDefinitions = bb - > getRD_In ( ) ;
2025-05-22 22:41:09 +03:00
vector < SAPFOR : : IR_Block * > instructions = bb - > getInstructions ( ) ;
2025-05-27 15:55:02 +03:00
for ( SAPFOR : : IR_Block * irBlock : instructions )
{
2025-05-24 19:56:15 +03:00
// 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
2025-05-22 22:41:09 +03:00
SAPFOR : : Instruction * instr = irBlock - > getInstruction ( ) ;
2025-05-24 19:56:15 +03:00
result [ instr - > getOperator ( ) ] ;
2025-05-22 22:41:09 +03:00
// take Argument 1 and it's RD and push operators to final set
2025-05-27 15:55:02 +03:00
if ( instr - > getArg1 ( ) ! = NULL )
{
2025-05-22 22:41:09 +03:00
SAPFOR : : Argument * arg = instr - > getArg1 ( ) ;
set < int > prevInstructionsNumbers = blockReachingDefinitions [ arg ] ;
2025-05-27 15:55:02 +03:00
for ( int i : prevInstructionsNumbers )
{
2025-05-22 22:41:09 +03:00
SAPFOR : : Instruction * foundInstruction = getInstructionAndBlockByNumber ( FullIR , i ) . first ;
2025-05-27 15:55:02 +03:00
if ( foundInstruction ! = NULL )
{
2025-05-22 22:41:09 +03:00
SgStatement * prevOp = foundInstruction - > getOperator ( ) ;
2025-05-27 01:41:50 +03:00
if ( prevOp ! = forStatement & & instr - > getOperator ( ) ! = forStatement & & instr - > getOperator ( ) - > lineNumber ( ) > prevOp - > lineNumber ( )
& & prevOp - > lineNumber ( ) > forStatement - > lineNumber ( ) )
2025-05-22 22:41:09 +03:00
result [ instr - > getOperator ( ) ] . insert ( prevOp ) ;
}
}
}
// take Argument 2 (if exists) and it's RD and push operators to final set
2025-05-27 15:55:02 +03:00
if ( instr - > getArg2 ( ) ! = NULL )
{
2025-05-22 22:41:09 +03:00
SAPFOR : : Argument * arg = instr - > getArg2 ( ) ;
set < int > prevInstructionsNumbers = blockReachingDefinitions [ arg ] ;
2025-05-27 15:55:02 +03:00
for ( int i : prevInstructionsNumbers )
{
2025-05-22 22:41:09 +03:00
SAPFOR : : Instruction * foundInstruction = getInstructionAndBlockByNumber ( FullIR , i ) . first ;
2025-05-27 15:55:02 +03:00
if ( foundInstruction ! = NULL )
{
2025-05-22 22:41:09 +03:00
SgStatement * prevOp = foundInstruction - > getOperator ( ) ;
2025-05-27 01:41:50 +03:00
if ( prevOp ! = forStatement & & instr - > getOperator ( ) ! = forStatement & & instr - > getOperator ( ) - > lineNumber ( ) > prevOp - > lineNumber ( )
& & prevOp - > lineNumber ( ) > forStatement - > lineNumber ( ) )
2025-05-22 22:41:09 +03:00
result [ instr - > getOperator ( ) ] . insert ( prevOp ) ;
}
}
}
// update RD
if ( instr - > getResult ( ) ! = NULL )
blockReachingDefinitions [ instr - > getResult ( ) ] = { instr - > getNumber ( ) } ;
}
}
2025-05-13 00:46:32 +03:00
return result ;
}
2025-05-24 23:15:30 +03:00
void buildAdditionalDeps ( SgForStmt * forStatement , map < SgStatement * , set < SgStatement * > > & dependencies )
{
SgStatement * lastNode = forStatement - > lastNodeOfStmt ( ) ;
vector < SgStatement * > importantDeps ;
SgStatement * st = ( SgStatement * ) forStatement ;
2025-05-27 01:41:50 +03:00
st = st - > lexNext ( ) ;
2025-05-24 23:15:30 +03:00
SgStatement * logIfOp = NULL ;
while ( st & & st ! = lastNode )
{
2025-05-27 01:41:50 +03:00
if ( importantDeps . size ( ) ! = 0 )
2025-05-27 15:55:02 +03:00
{
if ( st ! = importantDeps . back ( ) )
{
2025-05-27 01:41:50 +03:00
dependencies [ st ] . insert ( importantDeps . back ( ) ) ;
2025-05-27 15:55:02 +03:00
}
2025-05-24 23:15:30 +03:00
}
2025-05-27 15:55:02 +03:00
if ( logIfOp ! = NULL )
{
2025-05-24 23:15:30 +03:00
dependencies [ st ] . insert ( logIfOp ) ;
logIfOp = NULL ;
}
2025-05-27 15:55:02 +03:00
if ( st - > variant ( ) = = LOGIF_NODE )
{
2025-05-24 23:15:30 +03:00
logIfOp = st ;
}
2025-05-27 15:55:02 +03:00
if ( importantDepsTags . find ( st - > variant ( ) ) ! = importantDepsTags . end ( ) )
{
2025-05-24 23:15:30 +03:00
importantDeps . push_back ( st ) ;
}
2025-05-27 15:55:02 +03:00
if ( importantUpdDepsTags . find ( st - > variant ( ) ) ! = importantUpdDepsTags . end ( ) )
{
2025-05-24 23:15:30 +03:00
importantDeps . pop_back ( ) ;
2025-05-27 01:41:50 +03:00
importantDeps . push_back ( st ) ;
2025-05-24 23:15:30 +03:00
}
2025-05-27 15:55:02 +03:00
if ( importantEndTags . find ( st - > variant ( ) ) ! = importantEndTags . end ( ) )
{
2025-05-27 01:41:50 +03:00
if ( importantDeps . size ( ) ! = 0 )
2025-05-27 15:55:02 +03:00
{
2025-05-27 01:41:50 +03:00
importantDeps . pop_back ( ) ;
2025-05-27 15:55:02 +03:00
}
2025-05-24 19:56:15 +03:00
}
2025-05-27 01:41:50 +03:00
st = st - > lexNext ( ) ;
2025-05-24 19:56:15 +03:00
}
}
2025-05-27 01:41:50 +03:00
struct ReadyOp {
SgStatement * stmt ;
int degree ;
size_t arrival ;
ReadyOp ( SgStatement * s , int d , size_t a ) : stmt ( s ) , degree ( d ) , arrival ( a ) { }
} ;
2025-05-24 19:56:15 +03:00
2025-05-27 01:41:50 +03:00
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 ;
2025-05-24 19:56:15 +03:00
}
2025-05-27 01:41:50 +03:00
} ;
2025-05-24 19:56:15 +03:00
2025-05-27 15:55:02 +03:00
vector < SgStatement * > scheduleOperations ( const map < SgStatement * , set < SgStatement * > > & dependencies )
{
2025-05-27 01:41:50 +03:00
// get all statements
unordered_set < SgStatement * > allStmtsSet ;
2025-05-27 15:55:02 +03:00
for ( const auto & pair : dependencies )
{
2025-05-27 01:41:50 +03:00
allStmtsSet . insert ( pair . first ) ;
for ( SgStatement * dep : pair . second )
2025-05-27 15:55:02 +03:00
{
2025-05-27 01:41:50 +03:00
allStmtsSet . insert ( dep ) ;
2025-05-27 15:55:02 +03:00
}
2025-05-27 01:41:50 +03:00
}
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 ;
2025-05-27 15:55:02 +03:00
for ( const auto & pair : dependencies )
{
2025-05-27 01:41:50 +03:00
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 ) ;
2025-05-24 19:56:15 +03:00
}
2025-05-27 01:41:50 +03:00
for ( SgStatement * op : allStmts )
2025-05-27 15:55:02 +03:00
{
2025-05-27 01:41:50 +03:00
if ( ! degree . count ( op ) )
2025-05-27 15:55:02 +03:00
{
2025-05-27 01:41:50 +03:00
degree [ op ] = 0 ;
2025-05-27 15:55:02 +03:00
}
}
2025-05-27 01:41:50 +03:00
// build queues
using PQ = priority_queue < ReadyOp , vector < ReadyOp > , ReadyOpCompare > ;
PQ readyDependent ;
queue < SgStatement * > readyIndependent ;
size_t arrivalCounter = 0 ;
2025-05-27 15:55:02 +03:00
for ( auto op : allStmts )
{
if ( inDegree [ op ] = = 0 )
{
if ( dependentStmts . count ( op ) )
{
2025-05-27 01:41:50 +03:00
readyDependent . emplace ( op , degree [ op ] , arrivalCounter + + ) ;
2025-05-27 15:55:02 +03:00
}
else
{
2025-05-27 01:41:50 +03:00
readyIndependent . push ( op ) ;
}
}
2025-05-24 19:56:15 +03:00
}
2025-05-27 01:41:50 +03:00
// main sort algorythm
vector < SgStatement * > executionOrder ;
2025-05-27 15:55:02 +03:00
while ( ! readyDependent . empty ( ) | | ! readyIndependent . empty ( ) )
{
2025-05-27 01:41:50 +03:00
SgStatement * current = nullptr ;
2025-05-27 15:55:02 +03:00
if ( ! readyDependent . empty ( ) )
{
2025-05-27 01:41:50 +03:00
current = readyDependent . top ( ) . stmt ;
readyDependent . pop ( ) ;
2025-05-27 15:55:02 +03:00
}
else
{
2025-05-27 01:41:50 +03:00
current = readyIndependent . front ( ) ;
readyIndependent . pop ( ) ;
}
executionOrder . push_back ( current ) ;
2025-05-27 15:55:02 +03:00
for ( SgStatement * neighbor : graph [ current ] )
{
2025-05-27 01:41:50 +03:00
inDegree [ neighbor ] - - ;
if ( inDegree [ neighbor ] = = 0 ) {
2025-05-27 15:55:02 +03:00
if ( dependentStmts . count ( neighbor ) )
{
2025-05-27 01:41:50 +03:00
readyDependent . emplace ( neighbor , degree [ neighbor ] , arrivalCounter + + ) ;
2025-05-27 15:55:02 +03:00
}
else
{
2025-05-27 01:41:50 +03:00
readyIndependent . push ( neighbor ) ;
2025-05-24 19:56:15 +03:00
}
}
}
2025-05-22 22:41:09 +03:00
}
2025-05-27 01:41:50 +03:00
return executionOrder ;
2025-05-24 19:56:15 +03:00
}
2025-05-27 15:55:02 +03:00
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 ) ;
}
2025-05-27 01:41:50 +03:00
2025-05-22 22:41:09 +03:00
2025-05-13 00:46:32 +03:00
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
2025-05-27 01:41:50 +03:00
const int funcNum = file - > numberOfFunctions ( ) ;
2025-05-13 00:46:32 +03:00
for ( int i = 0 ; i < funcNum ; + + i )
{
2025-05-27 01:41:50 +03:00
SgStatement * st = file - > functions ( i ) ;
2025-05-13 00:46:32 +03:00
vector < SAPFOR : : BasicBlock * > blocks = findFuncBlocksByFuncStatement ( st , FullIR ) ;
map < SgForStmt * , vector < SAPFOR : : BasicBlock * > > loopsMapping = findAndAnalyzeLoops ( st , blocks ) ;
for ( pair < SgForStmt * , vector < SAPFOR : : BasicBlock * > > loopForAnalyze : loopsMapping )
{
2025-05-24 19:56:15 +03:00
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)
2025-05-24 23:15:30 +03:00
buildAdditionalDeps ( loopForAnalyze . first , dependencyGraph ) ;
2025-05-27 01:41:50 +03:00
cout < < endl ;
2025-05-24 23:15:30 +03:00
int firstLine = loopForAnalyze . first - > lineNumber ( ) ;
int lastLine = loopForAnalyze . first - > lastNodeOfStmt ( ) - > lineNumber ( ) ;
2025-05-27 01:41:50 +03:00
cout < < " LOOP ANALYZE FROM " < < firstLine < < " TO " < < lastLine < < " RES " < < endl ;
// for (auto &v: dependencyGraph) {
// cout << "OPERATOR: " << v.first -> lineNumber() << " " << v.first -> variant() << "\nDEPENDS ON:" << endl;
2025-05-24 23:15:30 +03:00
// if (v.second.size() != 0)
2025-05-27 01:41:50 +03:00
// for (auto vv: v.second)
// cout << vv -> lineNumber() << " ";
2025-05-24 23:15:30 +03:00
// cout << endl;
// }
2025-05-27 01:41:50 +03:00
vector < SgStatement * > new_order = scheduleOperations ( dependencyGraph ) ;
cout < < " RESULT ORDER: " < < endl ;
for ( auto v : new_order )
if ( v - > lineNumber ( ) > firstLine )
cout < < v - > lineNumber ( ) < < endl ;
2025-05-27 15:55:02 +03:00
buildNewAST ( loopForAnalyze . first , new_order ) ;
st = loopForAnalyze . first - > lexNext ( ) ;
while ( st ! = loopForAnalyze . first - > lastNodeOfStmt ( ) )
{
cout < < st - > lineNumber ( ) < < " " < < st - > sunparse ( ) < < endl ;
st = st - > lexNext ( ) ;
}
2025-05-13 00:46:32 +03:00
}
}
2025-03-25 15:18:49 +03:00
return ;
2025-05-13 00:46:32 +03:00
} ;