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*/ } ;
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 , std : : map < FuncInfo * , std : : 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 )
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-22 22:41:09 +03:00
for ( SAPFOR : : BasicBlock * bb : loopBlocks ) {
std : : map < SAPFOR : : Argument * , std : : set < int > > blockReachingDefinitions = bb - > getRD_In ( ) ;
vector < SAPFOR : : IR_Block * > instructions = bb - > getInstructions ( ) ;
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
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 ( ) )
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 ( ) )
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 19:56:15 +03:00
// int PrintSmthFromLoop(int firstLine, int lastLine, map<SgStatement*, unordered_set<SgStatement*>> moveRules) {
// // only cout done yet ((
// cout << "LOOP ANALYZE FROM " << firstLine << " TO " << lastLine << " RES\n" << endl;
// for (auto r: moveRules) {
// cout << "OPERATOR: " << endl;
// cout << r.first -> lineNumber() << r.first -> sunparse();
// cout << "DEPENDS FROM NEXT: " << endl;
// for (SgStatement* st: r.second)
// cout << st -> lineNumber() << endl;
// }
// cout << "\n\n\n";
// return 0;
// }
void GenNodesOfGraph (
const map < SgStatement * , set < SgStatement * > > & dependencies ,
set < SgStatement * > & allNodes ,
map < SgStatement * , set < SgStatement * > > & outEdges ,
map < SgStatement * , set < SgStatement * > > & inEdges )
{
for ( const auto & node : dependencies ) {
SgStatement * u = node . first ;
allNodes . insert ( u ) ;
for ( SgStatement * v : node . second ) {
allNodes . insert ( v ) ;
outEdges [ v ] . insert ( u ) ;
inEdges [ u ] . insert ( v ) ;
outEdges [ u ] ;
inEdges [ v ] ;
}
outEdges [ u ] ;
inEdges [ u ] ;
}
}
vector < set < SgStatement * > > FindLinksInGraph (
const set < SgStatement * > & allNodes ,
const map < SgStatement * , set < SgStatement * > > & outEdges ,
const map < SgStatement * , set < SgStatement * > > & inEdges )
{
set < SgStatement * > visited ;
vector < std : : set < SgStatement * > > components ;
for ( SgStatement * v : allNodes ) {
if ( visited . count ( v ) ) {
continue ;
}
set < SgStatement * > component ;
queue < SgStatement * > q ;
q . push ( v ) ;
visited . insert ( v ) ;
while ( ! q . empty ( ) ) {
SgStatement * curr = q . front ( ) ;
q . pop ( ) ;
component . insert ( curr ) ;
for ( SgStatement * neighbour : outEdges . at ( curr ) ) {
if ( ! visited . count ( neighbour ) ) {
q . push ( neighbour ) ; visited . insert ( neighbour ) ;
}
}
for ( SgStatement * neighbour : inEdges . at ( curr ) ) {
if ( ! visited . count ( neighbour ) ) {
q . push ( neighbour ) ; visited . insert ( neighbour ) ;
}
}
}
components . push_back ( component ) ;
}
return components ;
}
vector < SgStatement * > SortComponent (
const set < SgStatement * > & component ,
const map < SgStatement * , set < SgStatement * > > & outEdges ,
const map < SgStatement * , set < SgStatement * > > & inEdges )
{
map < SgStatement * , int > inDegree ;
for ( auto v : component ) {
inDegree [ v ] = inEdges . at ( v ) . size ( ) ;
}
queue < SgStatement * > q ;
for ( auto v : component ) {
if ( inDegree [ v ] = = 0 ) q . push ( v ) ;
}
vector < SgStatement * > result ;
while ( ! q . empty ( ) ) {
auto curr = q . front ( ) ;
q . pop ( ) ;
result . push_back ( curr ) ;
for ( SgStatement * neighbour : outEdges . at ( curr ) ) {
if ( component . count ( neighbour ) ) {
inDegree [ neighbour ] - - ;
if ( inDegree [ neighbour ] = = 0 ) {
q . push ( neighbour ) ;
}
}
}
2025-05-22 22:41:09 +03:00
}
2025-05-24 19:56:15 +03:00
return result ;
}
vector < SgStatement * > SortNoInterleaving ( const map < SgStatement * , set < SgStatement * > > & dependencies )
{
set < SgStatement * > allNodes ;
map < SgStatement * , set < SgStatement * > > outEdges , inEdges ;
GenNodesOfGraph ( dependencies , allNodes , outEdges , inEdges ) ;
auto components = FindLinksInGraph ( allNodes , outEdges , inEdges ) ;
vector < SgStatement * > totalOrder ;
for ( auto & comp : components ) {
auto part = SortComponent ( comp , outEdges , inEdges ) ;
totalOrder . insert ( totalOrder . end ( ) , part . begin ( ) , part . end ( ) ) ;
}
return totalOrder ;
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
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 )
{
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)
cout < < " \n \n " ;
for ( auto v : dependencyGraph ) {
cout < < " OPERATOR: " < < v . first - > lineNumber ( ) < < " \n DEPENDS ON: " < < endl ;
for ( auto vv : v . second ) {
cout < < vv - > lineNumber ( ) < < " " ;
}
cout < < endl ;
}
if ( dependencyGraph . size ( ) ! = 0 ) {
2025-05-22 22:41:09 +03:00
int firstLine = loopForAnalyze . first - > lineNumber ( ) ;
int lastLine = loopForAnalyze . first - > lastNodeOfStmt ( ) - > lineNumber ( ) ;
2025-05-24 19:56:15 +03:00
// countOfTransform += PrintSmthFromLoop(firstLine, lastLine, dependencyGraph);
vector < SgStatement * > new_order = SortNoInterleaving ( dependencyGraph ) ;
cout < < " \n \n LOOP ANALYZE FROM " < < firstLine < < " TO " < < lastLine < < " RES \n " < < endl ;
for ( auto v : new_order )
if ( v - > lineNumber ( ) > firstLine )
cout < < v - > lineNumber ( ) < < " " ;
2025-05-22 22:41:09 +03:00
}
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
} ;