This commit is contained in:
2025-03-12 12:37:19 +03:00
committed by Dudarenko
parent 0c9f0664fd
commit d4fb323f86
428 changed files with 0 additions and 0 deletions

524
Sapfor/CMakeLists.txt Normal file
View File

@@ -0,0 +1,524 @@
cmake_minimum_required(VERSION 3.10)
set(project Sapfor)
if (TARGET ${project})
return()
endif ()
project(${project})
message("processing ${project}")
#include(CTest)
add_definitions("-D SYS5")
add_definitions("-D YYDEBUG")
set(CMAKE_CXX_STANDARD 17)
set(fdvm_include ../../../dvm/fdvm/trunk/include)
set(sage_include_1 ../../../dvm/fdvm/trunk/Sage/lib/include)
set(sage_include_2 ../../../dvm/fdvm/trunk/Sage/h/)
set(libdb_sources ../../../dvm/fdvm/trunk/Sage/lib/oldsrc)
set(sage_sources ../../../dvm/fdvm/trunk/Sage/lib/newsrc)
set(sagepp_sources ../../../dvm/fdvm/trunk/Sage/Sage++)
set(parser_sources ../../../dvm/fdvm/trunk/parser)
set(pppa_sources ../../../dvm/tools/pppa/trunk/src)
set(zlib_sources ../../../dvm/tools/Zlib)
# Read pathes to external sapfor directories
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/paths.txt")
message("Found paths.txt, using custom paths.")
FILE(STRINGS ./paths.txt SAPFOR_PATHS)
else ()
message("Not found paths.txt, using default paths.")
FILE(STRINGS ./paths.default.txt SAPFOR_PATHS)
endif ()
foreach (NameAndValue ${SAPFOR_PATHS})
# Strip leading spaces
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
# Find variable name
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
# Find the value
string(REPLACE "${Name}=" "" Value ${NameAndValue})
# Set the variable, note the ../ because we are deeper than the file
set(${Name} "${Value}")
message("Using ${Name} ${${Name}}")
endforeach ()
include_directories(_src)
#Sage lib includes
include_directories(${fdvm_include})
include_directories(${sage_include_1})
include_directories(${sage_include_2})
#Zlib includes
include_directories(${zlib_sources}/include)
#PPPA includes
include_directories(${pppa_sources})
set(PR_PARAM _src/ProjectParameters/projectParameters.cpp
_src/ProjectParameters/projectParameters.h)
set(GR_LAYOUT _src/VisualizerCalls/graphLayout/algebra.cpp
_src/VisualizerCalls/graphLayout/algebra.hpp
_src/VisualizerCalls/graphLayout/fruchterman_reingold.cpp
_src/VisualizerCalls/graphLayout/fruchterman_reingold.hpp
_src/VisualizerCalls/graphLayout/kamada_kawai.cpp
_src/VisualizerCalls/graphLayout/kamada_kawai.hpp
_src/VisualizerCalls/graphLayout/layout.cpp
_src/VisualizerCalls/graphLayout/layout.hpp
_src/VisualizerCalls/graphLayout/nodesoup.cpp
_src/VisualizerCalls/graphLayout/nodesoup.hpp)
set(VS_CALLS _src/VisualizerCalls/get_information.cpp
_src/VisualizerCalls/get_information.h
_src/VisualizerCalls/SendMessage.cpp
_src/VisualizerCalls/SendMessage.h
_src/VisualizerCalls/BuildGraph.cpp
_src/VisualizerCalls/BuildGraph.h)
set(VERIF _src/VerificationCode/CorrectVarDecl.cpp
_src/VerificationCode/IncludeChecker.cpp
_src/VerificationCode/StructureChecker.cpp
_src/VerificationCode/VerifySageStructures.cpp
_src/VerificationCode/verifications.h)
set(UTILS _src/Utils/AstWrapper.h
_src/Utils/BoostStackTrace.cpp
_src/Utils/CommonBlock.h
_src/Utils/DefUseList.h
_src/Utils/errors.h
_src/Utils/leak_detector.h
_src/Utils/RationalNum.cpp
_src/Utils/RationalNum.h
_src/Utils/SgUtils.cpp
_src/Utils/SgUtils.h
_src/Utils/types.h
_src/Utils/utils.cpp
_src/Utils/utils.h
_src/Utils/version.h
_src/Utils/module_utils.h
_src/Utils/module_utils.cpp)
set(OMEGA _src/SageAnalysisTool/OmegaForSage/add-assert.cpp
_src/SageAnalysisTool/OmegaForSage/affine.cpp
_src/SageAnalysisTool/OmegaForSage/cover.cpp
_src/SageAnalysisTool/OmegaForSage/ddomega-build.cpp
_src/SageAnalysisTool/OmegaForSage/ddomega-use.cpp
_src/SageAnalysisTool/OmegaForSage/ddomega.cpp
_src/SageAnalysisTool/OmegaForSage/debug.cpp
_src/SageAnalysisTool/OmegaForSage/ip.cpp
_src/SageAnalysisTool/OmegaForSage/kill.cpp
_src/SageAnalysisTool/OmegaForSage/refine.cpp
_src/SageAnalysisTool/OmegaForSage/sagedriver.cpp
_src/SageAnalysisTool/annotationDriver.cpp
_src/SageAnalysisTool/arrayRef.cpp
_src/SageAnalysisTool/computeInducVar.cpp
_src/SageAnalysisTool/constanteProp.cpp
_src/SageAnalysisTool/constanteSet.h
_src/SageAnalysisTool/controlFlow.cpp
_src/SageAnalysisTool/defUse.cpp
_src/SageAnalysisTool/dependence.cpp
_src/SageAnalysisTool/depGraph.cpp
_src/SageAnalysisTool/depInterface.cpp
_src/SageAnalysisTool/depInterfaceExt.h
_src/SageAnalysisTool/flowAnalysis.cpp
_src/SageAnalysisTool/inducVar.h
_src/SageAnalysisTool/intrinsic.cpp
_src/SageAnalysisTool/invariant.cpp
_src/SageAnalysisTool/loopTransform.cpp
_src/SageAnalysisTool/set.cpp)
set(PRIV _src/PrivateAnalyzer/private_analyzer.cpp
_src/PrivateAnalyzer/private_analyzer.h)
set(FDVM ${fdvm_sources}/acc.cpp
${fdvm_sources}/acc_across.cpp
${fdvm_sources}/acc_across_analyzer.cpp
${fdvm_sources}/acc_analyzer.cpp
${fdvm_sources}/acc_data.cpp
${fdvm_sources}/acc_f2c.cpp
${fdvm_sources}/acc_f2c_handlers.cpp
${fdvm_sources}/acc_rtc.cpp
${fdvm_sources}/acc_rtc.cpp
${fdvm_sources}/acc_utilities.cpp
${fdvm_sources}/aks_analyzeLoops.cpp
${fdvm_sources}/aks_structs.cpp
${fdvm_sources}/checkpoint.cpp
${fdvm_sources}/debug.cpp
${fdvm_sources}/dvm.cpp
${fdvm_sources}/calls.cpp
${fdvm_sources}/funcall.cpp
${fdvm_sources}/help.cpp
${fdvm_sources}/hpf.cpp
${fdvm_sources}/io.cpp
${fdvm_sources}/omp.cpp
${fdvm_sources}/ompdebug.cpp
${fdvm_sources}/parloop.cpp
${fdvm_sources}/stmt.cpp)
set(PARALLEL_REG _src/ParallelizationRegions/ParRegions.cpp
_src/ParallelizationRegions/ParRegions.h
_src/ParallelizationRegions/ParRegions_func.h
_src/ParallelizationRegions/expand_extract_reg.cpp
_src/ParallelizationRegions/expand_extract_reg.h
_src/ParallelizationRegions/resolve_par_reg_conflicts.cpp
_src/ParallelizationRegions/resolve_par_reg_conflicts.h)
set(TR_DEAD_CODE _src/Transformations/dead_code.cpp
_src/Transformations/dead_code.h)
set(TR_CP _src/Transformations/checkpoints.cpp
_src/Transformations/checkpoints.h)
set(TR_VECTOR _src/Transformations/array_assign_to_loop.cpp
_src/Transformations/array_assign_to_loop.h)
set(TR_ENDDO_LOOP _src/Transformations/enddo_loop_converter.cpp
_src/Transformations/enddo_loop_converter.h)
set(TR_LOOP_NEST _src/Transformations/loop_transform.cpp
_src/Transformations/loop_transform.h)
set(TR_LOOP_COMB _src/Transformations/loops_combiner.cpp
_src/Transformations/loops_combiner.h)
set(TR_LOOP_SPLIT _src/Transformations/loops_splitter.cpp
_src/Transformations/loops_splitter.h)
set(TR_LOOP_UNROLL _src/Transformations/loops_unrolling.cpp
_src/Transformations/loops_unrolling.h)
set(TR_PRIV_BR _src/Transformations/private_arrays_resizing.cpp
_src/Transformations/private_arrays_resizing.h)
set(TR_PRIV_DEL _src/Transformations/private_removing.cpp
_src/Transformations/private_removing.h)
set(TR_SWAP_ARR_DIMS _src/Transformations/swap_array_dims.cpp
_src/Transformations/swap_array_dims.h)
set(TR_FUNC_DUP _src/Transformations/uniq_call_chain_dup.cpp
_src/Transformations/uniq_call_chain_dup.h)
set(TR_FUNC_PURE _src/Transformations/function_purifying.cpp
_src/Transformations/function_purifying.h)
set(TR_GV _src/Transformations/fix_common_blocks.cpp
_src/Transformations/fix_common_blocks.h)
set(TR_CONV _src/Transformations/convert_to_c.cpp
_src/Transformations/convert_to_c.h)
set(TR_IMPLICIT_NONE _src/Transformations/set_implicit_none.cpp
_src/Transformations/set_implicit_none.h)
set(TR_REPLACE_ARRAYS_IN_IO _src/Transformations/replace_dist_arrays_in_io.cpp
_src/Transformations/replace_dist_arrays_in_io.h)
set(TRANSFORMS
${TR_DEAD_CODE}
${TR_CP}
${TR_VECTOR}
${TR_ENDDO_LOOP}
${TR_LOOP_NEST}
${TR_LOOP_COMB}
${TR_LOOP_SPLIT}
${TR_PRIV_BR}
${TR_SWAP_ARR_DIMS}
${TR_FUNC_DUP}
${TR_FUNC_PURE}
${TR_LOOP_UNROLL}
${TR_GV}
${TR_PRIV_DEL}
${TR_CONV}
${TR_PRIV_DEL}
${TR_IMPLICIT_NONE}
${TR_REPLACE_ARRAYS_IN_IO})
set(CFG _src/CFGraph/IR.cpp
_src/CFGraph/IR.h
_src/CFGraph/CFGraph.cpp
_src/CFGraph/CFGraph.h
_src/CFGraph/RD_subst.cpp
_src/CFGraph/RD_subst.h
_src/CFGraph/live_variable_analysis.cpp
_src/CFGraph/live_variable_analysis.h
_src/CFGraph/private_variables_analysis.cpp
_src/CFGraph/private_variables_analysis.h
_src/CFGraph/IRSSAForm.cpp
_src/CFGraph/IRSSAForm.h
)
set(DATA_FLOW
_src/CFGraph/DataFlow/data_flow.h
_src/CFGraph/DataFlow/data_flow_impl.h
_src/CFGraph/DataFlow/backward_data_flow.h
_src/CFGraph/DataFlow/backward_data_flow_impl.h
)
set(CREATE_INTER_T _src/CreateInterTree/CreateInterTree.cpp
_src/CreateInterTree/CreateInterTree.h)
set(DIRA _src/DirectiveProcessing/directive_analyzer.cpp
_src/DirectiveProcessing/directive_analyzer.h
_src/DirectiveProcessing/directive_creator.cpp
_src/DirectiveProcessing/directive_creator_base.cpp
_src/DirectiveProcessing/directive_creator.h
_src/DirectiveProcessing/directive_parser.cpp
_src/DirectiveProcessing/directive_parser.h
_src/DirectiveProcessing/directive_omp_parser.cpp
_src/DirectiveProcessing/directive_omp_parser.h
_src/DirectiveProcessing/insert_directive.cpp
_src/DirectiveProcessing/insert_directive.h
_src/DirectiveProcessing/remote_access.cpp
_src/DirectiveProcessing/remote_access_base.cpp
_src/DirectiveProcessing/remote_access.h
_src/DirectiveProcessing/shadow.cpp
_src/DirectiveProcessing/shadow.h
_src/DirectiveProcessing/spf_directive_preproc.cpp)
set(DISTR _src/Distribution/Array.cpp
_src/Distribution/ArrayAnalysis.cpp
_src/Distribution/Array.h
_src/Distribution/Arrays.h
_src/Distribution/CreateDistributionDirs.cpp
_src/Distribution/CreateDistributionDirs.h
_src/Distribution/Cycle.cpp
_src/Distribution/Cycle.h
_src/Distribution/Distribution.cpp
_src/Distribution/Distribution.h
_src/Distribution/DvmhDirective.cpp
_src/Distribution/DvmhDirective.h
_src/Distribution/DvmhDirective_func.h
_src/Distribution/DvmhDirectiveBase.cpp
_src/Distribution/DvmhDirectiveBase.h
_src/Distribution/GraphCSR.cpp
_src/Distribution/GraphCSR.h)
set(DVMH_REG _src/DvmhRegions/DvmhRegionInserter.cpp
_src/DvmhRegions/DvmhRegionInserter.h
_src/DvmhRegions/RegionsMerger.cpp
_src/DvmhRegions/RegionsMerger.h
_src/DvmhRegions/ReadWriteAnalyzer.cpp
_src/DvmhRegions/ReadWriteAnalyzer.h
_src/DvmhRegions/LoopChecker.cpp
_src/DvmhRegions/LoopChecker.h
_src/DvmhRegions/DvmhRegion.cpp
_src/DvmhRegions/DvmhRegion.h
_src/DvmhRegions/VarUsages.cpp
_src/DvmhRegions/VarUsages.h
_src/DvmhRegions/TypedSymbol.cpp
_src/DvmhRegions/TypedSymbol.h)
set(DYNA _src/DynamicAnalysis/createParallelRegions.cpp
_src/DynamicAnalysis/createParallelRegions.h
_src/DynamicAnalysis/gcov_info.cpp
_src/DynamicAnalysis/gcov_info.h
_src/DynamicAnalysis/gCov_parser.cpp
_src/DynamicAnalysis/gCov_parser_func.h)
set(EXPR_TRANSFORM _src/ExpressionTransform/control_flow_graph_part.cpp
_src/ExpressionTransform/expr_transform.cpp
_src/ExpressionTransform/expr_transform.h)
set(GR_CALL _src/GraphCall/graph_calls.cpp
_src/GraphCall/graph_calls.h
_src/GraphCall/graph_calls_base.cpp
_src/GraphCall/graph_calls_func.h)
set(GR_LOOP _src/GraphLoop/graph_loops_base.cpp
_src/GraphLoop/graph_loops.cpp
_src/GraphLoop/graph_loops.h
_src/GraphLoop/graph_loops_func.h)
set(INLINER _src/Inliner/inliner.cpp
_src/Inliner/inliner.h)
set(LOOP_ANALYZER _src/LoopAnalyzer/allocations_prepoc.cpp
_src/LoopAnalyzer/dep_analyzer.cpp
_src/LoopAnalyzer/loop_analyzer.cpp
_src/LoopAnalyzer/loop_analyzer.h)
set(RENAME_SYMBOLS _src/RenameSymbols/rename_symbols.cpp
_src/RenameSymbols/rename_symbols.h)
set(MAIN _src/Sapfor.cpp
_src/Sapfor.h
_src/SapforData.h
_src/Utils/PassManager.h)
set(PREDICTOR _src/Predictor/PredictScheme.cpp
_src/Predictor/PredictScheme.h)
set(PROJ_MAN _src/ProjectManipulation/ParseFiles.cpp
_src/ProjectManipulation/ParseFiles.h
_src/ProjectManipulation/StdCapture.h
_src/ProjectManipulation/PerfAnalyzer.cpp
_src/ProjectManipulation/PerfAnalyzer.h
_src/ProjectManipulation/FileInfo.cpp
_src/ProjectManipulation/FileInfo.h
_src/ProjectManipulation/ConvertFiles.cpp
_src/ProjectManipulation/ConvertFiles.h)
set(PARSER ${parser_sources}/cftn.c
${parser_sources}/errors.c
${parser_sources}/gram1.tab.c
${parser_sources}/hash.c
${parser_sources}/init.c
${parser_sources}/lexfdvm.c
${parser_sources}/lists.c
${parser_sources}/low_hpf.c
${parser_sources}/misc.c
${parser_sources}/stat.c
${parser_sources}/sym.c
${parser_sources}/types.c
${parser_sources}/unparse_hpf.c)
set(PPPA ${pppa_sources}/inter.cpp
${pppa_sources}/potensyn.cpp
${pppa_sources}/stat.cpp
${pppa_sources}/statfile.cpp
${pppa_sources}/statinter.cpp
${pppa_sources}/statlist.cpp
${pppa_sources}/statprintf.cpp
${pppa_sources}/statread.cpp
${pppa_sources}/treeinter.cpp
${pppa_sources}/bool.h
${pppa_sources}/dvmh_stat.h
${pppa_sources}/inter.h
${pppa_sources}/potensyn.h
${pppa_sources}/statist.h
${pppa_sources}/statlist.h
${pppa_sources}/statprintf.h
${pppa_sources}/statread.h
${pppa_sources}/strall.h
${pppa_sources}/sysstat.h
${pppa_sources}/treeinter.h
${pppa_sources}/ver.h
${pppa_sources}/statinter.h
${pppa_sources}/json.hpp)
set(ZLIB ${zlib_sources}/src/adler32.c
${zlib_sources}/src/compress.c
${zlib_sources}/src/crc32.c
${zlib_sources}/src/deflate.c
${zlib_sources}/src/gzio.c
${zlib_sources}/src/infblock.c
${zlib_sources}/src/infcodes.c
${zlib_sources}/src/inffast.c
${zlib_sources}/src/inflate.c
${zlib_sources}/src/inftrees.c
${zlib_sources}/src/infutil.c
${zlib_sources}/src/trees.c
${zlib_sources}/src/uncompr.c
${zlib_sources}/src/zutil.c)
set(SOURCE_EXE
${CFG}
${DATA_FLOW}
${CREATE_INTER_T}
${DIRA}
${DISTR}
${DVMH_REG}
${DYNA}
${EXPR_TRANSFORM}
${GR_CALL}
${GR_LOOP}
${INLINER}
${LOOP_ANALYZER}
${RENAME_SYMBOLS}
${TRANSFORMS}
${PARALLEL_REG}
${PRIV}
${FDVM}
${OMEGA}
${UTILS}
${VERIF}
${VS_CALLS}
${MAIN}
${PREDICTOR}
${PARSER}
${PPPA}
${ZLIB}
${GR_LAYOUT}
${PR_PARAM}
${PROJ_MAN})
add_executable(Sapfor_F ${SOURCE_EXE})
source_group (CFGraph FILES ${CFG})
source_group (CFGraph\\DataFlow FILES ${DATA_FLOW})
source_group (Transformations\\DeadCodeRemoving FILES ${TR_DEAD_CODE})
source_group (Transformations\\ExpressionSubstitution FILES ${EXPR_TRANSFORM})
source_group (Transformations\\CheckPoints FILES ${TR_CP})
source_group (Transformations\\LoopEndDoConverter FILES ${TR_ENDDO_LOOP})
source_group (Transformations\\LoopNesting FILES ${TR_LOOP_NEST})
source_group (Transformations\\LoopCombining FILES ${TR_LOOP_COMB})
source_group (Transformations\\LoopSplitting FILES ${TR_LOOP_SPLIT})
source_group (Transformations\\LoopUnrolling FILES ${TR_LOOP_UNROLL})
source_group (Transformations\\FunctionDuplication FILES ${TR_FUNC_DUP})
source_group (Transformations\\FunctionInlining FILES ${INLINER})
source_group (Transformations\\FunctionPurifying FILES ${TR_FUNC_PURE})
source_group (Transformations\\ArrayDimsSwapping FILES ${TR_SWAP_ARR_DIMS})
source_group (Transformations\\PrivateArrayResizing FILES ${TR_PRIV_BR})
source_group (Transformations\\PrivateArrayRemoving FILES ${TR_PRIV_DEL})
source_group (Transformations\\VectorAssignToLoop FILES ${TR_VECTOR})
source_group (Transformations\\RenameSymbols FILES ${RENAME_SYMBOLS})
source_group (Transformations\\GlobalVariables FILES ${TR_GV})
source_group (Transformations\\ConvertToC FILES ${TR_CONV})
source_group (Transformations\\SetImplicitNone FILES ${TR_IMPLICIT_NONE})
source_group (Transformations\\ReplaceArraysInIO FILES ${TR_REPLACE_ARRAYS_IN_IO})
source_group (CreateIntervals FILES ${CREATE_INTER_T})
source_group (DirectiveProcessing FILES ${DIRA})
source_group (Distribution FILES ${DISTR})
source_group (DvmhRegions FILES ${DVMH_REG})
source_group (DynamicAnalysis FILES ${DYNA})
source_group (GraphCall FILES ${GR_CALL})
source_group (GraphLoop FILES ${GR_LOOP})
source_group (LoopAnalyzer FILES ${LOOP_ANALYZER})
source_group (ParallelizationRegions FILES ${PARALLEL_REG})
source_group (PrivateAnalyzer FILES ${PRIV})
source_group (FDVM_Compiler FILES ${FDVM})
source_group (SageExtension FILES ${OMEGA})
source_group (Utils FILES ${UTILS})
source_group (VerificationCode FILES ${VERIF})
source_group (ProjectParameters FILES ${PR_PARAM})
source_group (ProjectManipulation FILES ${PROJ_MAN})
source_group (VisualizerCalls FILES ${VS_CALLS})
source_group (VisualizerCalls\\GraphLayout FILES ${GR_LAYOUT})
source_group (_SapforMain FILES ${MAIN})
source_group (Predictor FILES ${PREDICTOR})
source_group (Parser FILES ${PARSER})
source_group (PPPA\\PPPA FILES ${PPPA})
source_group (PPPA\\ZLib FILES ${ZLIB})
if (MSVC_IDE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /Zc:__cplusplus")
else()
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
endif()
add_subdirectory(FDVM)
add_definitions("-D __SPF")
add_definitions("-D _CRT_SECURE_NO_WARNINGS")
add_definitions("-D _CRT_NON_CONFORMING_SWPRINTFS")
add_subdirectory(SageOldSrc)
add_subdirectory(SageNewSrc)
add_subdirectory(SageLib)
add_subdirectory(Parser)
add_definitions("-D __SPF_BUILT_IN_FDVM")
add_definitions("-D __SPF_BUILT_IN_PARSER")
add_definitions("-D __SPF_BUILT_IN_PPPA")
if (WIN32)
target_link_libraries(Sapfor_F SageNewSrc SageLib SageOldSrc)
elseif(APPLE)
target_link_libraries(Sapfor_F SageNewSrc SageLib SageOldSrc pthread)
elseif(UNIX)
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0)
target_link_libraries(Sapfor_F SageNewSrc SageLib SageOldSrc pthread stdc++fs)
else()
target_link_libraries(Sapfor_F SageNewSrc SageLib SageOldSrc pthread)
endif()
endif()
#install(TARGETS <name.exe/dll>
# LIBRARY DESTINATION <name_f>
# RUNTIME DESTINATION <name_f>)

View File

@@ -0,0 +1,83 @@
cmake_minimum_required(VERSION 3.10)
set(project FDVM)
#set(CMAKE_C_STANDARD 11)
#also named as libSage++
if (TARGET ${project})
return()
endif ()
project(${project})
message("processing ${project}")
# Read pathes to external sapfor directories
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../paths.txt")
message("Found paths.txt, using custom paths.")
FILE(STRINGS ../paths.txt SAPFOR_PATHS)
else ()
message("Not found paths.txt, using default paths.")
FILE(STRINGS ../paths.default.txt SAPFOR_PATHS)
endif ()
foreach (NameAndValue ${SAPFOR_PATHS})
# Strip leading spaces
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
# Find variable name
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
# Find the value
string(REPLACE "${Name}=" "" Value ${NameAndValue})
# Set the variable, note the ../ because we are deeper than the file
set(${Name} "../${Value}")
endforeach ()
set(SOURCE_LIB
${sagepp_sources}/libSage++.cpp
${sage_include_1}/libSage++.h)
# if not default ${sagepp_sources} must be set in ../paths.txt
set(SOURCE_EXE
${fdvm_sources}/acc.cpp
${fdvm_sources}/acc_across.cpp
${fdvm_sources}/acc_across_analyzer.cpp
${fdvm_sources}/acc_analyzer.cpp
${fdvm_sources}/acc_data.cpp
${fdvm_sources}/acc_f2c.cpp
${fdvm_sources}/acc_f2c_handlers.cpp
${fdvm_sources}/acc_rtc.cpp
${fdvm_sources}/acc_rtc.cpp
${fdvm_sources}/acc_utilities.cpp
${fdvm_sources}/aks_analyzeLoops.cpp
${fdvm_sources}/aks_structs.cpp
${fdvm_sources}/checkpoint.cpp
${fdvm_sources}/debug.cpp
${fdvm_sources}/dvm.cpp
${fdvm_sources}/calls.cpp
${fdvm_sources}/funcall.cpp
${fdvm_sources}/help.cpp
${fdvm_sources}/hpf.cpp
${fdvm_sources}/io.cpp
${fdvm_sources}/omp.cpp
${fdvm_sources}/ompdebug.cpp
${fdvm_sources}/parloop.cpp
${fdvm_sources}/stmt.cpp)
source_group (SageLib FILES ${SOURCE_LIB})
# if not default ${fdvm_include}, ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
include_directories(${fdvm_include} ${sage_include_1} ${sage_include_2})
add_executable(FDVM ${SOURCE_EXE} ${SOURCE_LIB})
if (MSVC_IDE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()
add_definitions("-D _CRT_SECURE_NO_WARNINGS")
add_definitions("-D SYS5")
add_definitions("-D YYDEBUG")
add_subdirectory(../SageOldSrc ${CMAKE_CURRENT_BINARY_DIR}/SageOldSrc)
add_subdirectory(../SageNewSrc ${CMAKE_CURRENT_BINARY_DIR}/SageNewSrc)
target_link_libraries(FDVM SageOldSrc SageNewSrc)

View File

@@ -0,0 +1,66 @@
cmake_minimum_required(VERSION 3.10)
set(project Parser)
#set(CMAKE_C_STANDARD 11)
#also named as libSage++
if (TARGET ${project})
return()
endif ()
project(${project})
message("processing ${project}")
# Read pathes to external sapfor directories
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../paths.txt")
message("Found paths.txt, using custom paths.")
FILE(STRINGS ../paths.txt SAPFOR_PATHS)
else ()
message("Not found paths.txt, using default paths.")
FILE(STRINGS ../paths.default.txt SAPFOR_PATHS)
endif ()
foreach (NameAndValue ${SAPFOR_PATHS})
# Strip leading spaces
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
# Find variable name
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
# Find the value
string(REPLACE "${Name}=" "" Value ${NameAndValue})
# Set the variable, note the ../ because we are deeper than the file
set(${Name} "../${Value}")
endforeach ()
# if not default ${sagepp_sources} must be set in ../paths.txt
set(SOURCE_EXE
${parser_sources}/cftn.c
${parser_sources}/errors.c
${parser_sources}/gram1.tab.c
${parser_sources}/hash.c
${parser_sources}/init.c
${parser_sources}/lexfdvm.c
${parser_sources}/lists.c
${parser_sources}/low_hpf.c
${parser_sources}/misc.c
${parser_sources}/stat.c
${parser_sources}/sym.c
${parser_sources}/types.c
${parser_sources}/unparse_hpf.c
)
# if not default ${fdvm_include}, ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
include_directories(${fdvm_include} ${sage_include_1} ${sage_include_2})
add_executable(Parser ${SOURCE_EXE})
if (MSVC_IDE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()
add_definitions("-D __SPF")
add_definitions("-D _CRT_SECURE_NO_WARNINGS")
add_definitions("-D SYS5")
add_definitions("-D YYDEBUG")
add_subdirectory(../SageOldSrc ${CMAKE_CURRENT_BINARY_DIR}/SageOldSrc)
target_link_libraries(Parser SageOldSrc)

View File

@@ -0,0 +1,49 @@
cmake_minimum_required(VERSION 3.10)
set(project SageLib)
#also named as libSage++
if (TARGET ${project})
return()
endif ()
project(${project})
message("processing ${project}")
# Read pathes to external sapfor directories
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../paths.txt")
message("Found paths.txt, using custom paths.")
FILE(STRINGS ../paths.txt SAPFOR_PATHS)
else ()
message("Not found paths.txt, using default paths.")
FILE(STRINGS ../paths.default.txt SAPFOR_PATHS)
endif ()
foreach (NameAndValue ${SAPFOR_PATHS})
# Strip leading spaces
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
# Find variable name
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
# Find the value
string(REPLACE "${Name}=" "" Value ${NameAndValue})
# Set the variable, note the ../ because we are deeper than the file
set(${Name} "../${Value}")
endforeach ()
# if not default ${sagepp_sources} must be set in ../paths.txt
set(SOURCE_LIB
${sagepp_sources}/libSage++.cpp
${sage_include_1}/libSage++.h
)
# if not default ${fdvm_include}, ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
include_directories(${fdvm_include} ${sage_include_1} ${sage_include_2})
add_library(SageLib STATIC ${SOURCE_LIB})
add_subdirectory(../SageOldSrc ${CMAKE_CURRENT_BINARY_DIR}/SageOldSrc)
target_link_libraries(SageLib SageOldSrc)
if (MSVC_IDE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()

View File

@@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 3.10)
set(project SageNewSrc)
#set(CMAKE_C_STANDARD 11)
#also named as libSage
if (TARGET ${project})
return()
endif ()
project(${project})
message("processing ${project}")
# Read pathes to external sapfor directories
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../paths.txt")
message("Found paths.txt, using custom paths.")
FILE(STRINGS ../paths.txt SAPFOR_PATHS)
else ()
message("Not found paths.txt, using default paths.")
FILE(STRINGS ../paths.default.txt SAPFOR_PATHS)
endif ()
foreach (NameAndValue ${SAPFOR_PATHS})
# Strip leading spaces
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
# Find variable name
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
# Find the value
string(REPLACE "${Name}=" "" Value ${NameAndValue})
# Set the variable, note the ../ because we are deeper than the file
set(${Name} "../${Value}")
endforeach ()
# if not default ${sage_sources} must be set in ../paths.txt
set(SOURCE_LIB
${sage_sources}/annotate.tab.c
${sage_sources}/comments.c
${sage_sources}/low_level.c
${sage_sources}/toolsann.c
${sage_sources}/unparse.c
)
# if not default ${fdvm_include}, ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
include_directories(${fdvm_include} ${sage_include_1} ${sage_include_2})
add_library(SageNewSrc STATIC ${SOURCE_LIB})
add_subdirectory(../SageOldSrc ${CMAKE_CURRENT_BINARY_DIR}/SageOldSrc)
target_link_libraries(SageNewSrc SageOldSrc)
if (MSVC_IDE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3")
endif()

View File

@@ -0,0 +1,63 @@
cmake_minimum_required(VERSION 3.10)
set(project SageOldSrc)
#set(CMAKE_C_STANDARD 11)
#also named as libDB
if (TARGET ${project})
return()
endif ()
project(${project})
message("processing ${project}")
# Read pathes to external sapfor directories
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../paths.txt")
message("Found paths.txt, using custom paths.")
FILE(STRINGS ../paths.txt SAPFOR_PATHS)
else ()
message("Not found paths.txt, using default paths.")
FILE(STRINGS ../paths.default.txt SAPFOR_PATHS)
endif ()
foreach (NameAndValue ${SAPFOR_PATHS})
# Strip leading spaces
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
# Find variable name
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
# Find the value
string(REPLACE "${Name}=" "" Value ${NameAndValue})
# Set the variable, note the ../ because we are deeper than the file
set(${Name} "../${Value}")
endforeach ()
# if not default ${libdb_sources} must be set in ../paths.txt
set(SOURCE_LIB
${libdb_sources}/anal_ind.c
${libdb_sources}/db.c
${libdb_sources}/dbutils.c
${libdb_sources}/db_unp.c
${libdb_sources}/db_unp_comm.c
${libdb_sources}/db_unp_vpc.c
${libdb_sources}/garb_coll.c
${libdb_sources}/glob_anal.c
${libdb_sources}/ker_fun.c
${libdb_sources}/list.c
${libdb_sources}/make_nodes.c
${libdb_sources}/mod_ref.c
${libdb_sources}/ndeps.c
${libdb_sources}/readnodes.c
${libdb_sources}/sets.c
${libdb_sources}/setutils.c
${libdb_sources}/symb_alg.c
${libdb_sources}/writenodes.c
)
# if not default ${fdvm_include}, ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
include_directories(${fdvm_include} ${sage_include_1} ${sage_include_2})
add_library(SageOldSrc STATIC ${SOURCE_LIB})
if (MSVC_IDE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()

31
Sapfor/Sapc++/Sapc++.sln Normal file
View File

@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2020
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sapc++", "Sapc++\Sapc++.vcxproj", "{DF2410E0-8B0A-420D-AC01-5DAFC460C816}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Debug|x64.ActiveCfg = Debug|x64
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Debug|x64.Build.0 = Debug|x64
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Debug|x86.ActiveCfg = Debug|Win32
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Debug|x86.Build.0 = Debug|Win32
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Release|x64.ActiveCfg = Release|x64
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Release|x64.Build.0 = Release|x64
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Release|x86.ActiveCfg = Release|Win32
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C1D1EA6C-5160-4B72-8353-388C68748C18}
EndGlobalSection
EndGlobal

468
Sapfor/Sapfor/Makefile Normal file
View File

@@ -0,0 +1,468 @@
########################################################################
# Makefile for Sapfor 2017
########################################################################
LIBDIR = ../_lib
BINDIR = ../_bin
SRCDIR = ../_src
CXX = g++
CC = gcc
CFLAGS = -O3 -D__SPF
STD=c++11
REPO_FDVM_BASE = ../../../../dvm/fdvm/trunk/
REPO_SPF_BASE = ../_src/
SAGE_BASE_DIR = $(REPO_FDVM_BASE)Sage/
SAGE_SRC_DIR = $(SAGE_BASE_DIR)Sage++/
SAGE_SRC_NEW = $(SAGE_BASE_DIR)lib/newsrc/
SAGE_SRC_OLD = $(SAGE_BASE_DIR)lib/oldsrc/
SAGE_INCL_DIR = $(SAGE_BASE_DIR)/h
LIB_INCL = $(SAGE_BASE_DIR)/lib/include
DVMINCLUDE = $(REPO_FDVM_BASE)/include
PARSER_BASE_DIR = $(REPO_FDVM_BASE)parser/
INLINER_BASE_DIR = $(REPO_FDVM_BASE)InlineExpansion/
all: $(LIBDIR)/libPred.a $(LIBDIR)/libSage++.a $(LIBDIR)/SageNewSrc.a $(LIBDIR)/SageOldSrc.a $(BINDIR)/Parser $(BINDIR)/Inliner $(BINDIR)/Sapfor
#Make Predictor
PS=$(REPO_SPF_BASE)Predictor/Lib/
PRED_OBJ_C=adler32.o compress.o crc32.o deflate.o gzio.o infblock.o infcodes.o inffast.o inflate.o inftrees.o infutil.o \
trees.o uncompr.o zutil.o
PRED_SOURCE_C=$(PS)adler32.c $(PS)compress.c $(PS)crc32.c $(PS)deflate.c $(PS)gzio.c $(PS)infblock.c $(PS)infcodes.c $(PS)inffast.c \
$(PS)inflate.c $(PS)inftrees.c $(PS)infutil.c $(PS)trees.c $(PS)uncompr.c $(PS)zutil.c
PRED_OBJ_CPP=AlignAxis.o AMView.o BGroup.o Block.o CallParams.o CommCost.o DArray.o DimBound.o DistAxis.o Event.o FuncCall.o \
Interval.o IntervalTemplate.o LoopBlock.o LoopLS.o Ls.o ModelDArray.o ModelInterval.o ModelIO.o ModelMPS_AM.o ModelParLoop.o \
ModelReduct.o ModelRegular.o ModelRemAccess.o ModelShadow.o ParLoop.o ParseString.o Processor.o Ps.o RedGroup.o RedVar.o \
RemAccessBuf.o Space.o TraceLine.o Vm.o intersection.o predictor.o
PRED_SOURCE_CPP=$(PS)AlignAxis.cpp $(PS)AMView.cpp $(PS)BGroup.cpp $(PS)Block.cpp $(PS)CallParams.cpp $(PS)CommCost.cpp $(PS)DArray.cpp \
$(PS)DimBound.cpp $(PS)DistAxis.cpp $(PS)Event.cpp $(PS)FuncCall.cpp $(PS)Interval.cpp $(PS)IntervalTemplate.cpp $(PS)LoopBlock.cpp \
$(PS)LoopLS.cpp $(PS)Ls.cpp $(PS)ModelDArray.cpp $(PS)ModelInterval.cpp $(PS)ModelIO.cpp $(PS)ModelMPS_AM.cpp $(PS)ModelParLoop.cpp \
$(PS)ModelReduct.cpp $(PS)ModelRegular.cpp $(PS)ModelRemAccess.cpp $(PS)ModelShadow.cpp $(PS)ParLoop.cpp $(PS)ParseString.cpp \
$(PS)Processor.cpp $(PS)Ps.cpp $(PS)RedGroup.cpp $(PS)RedVar.cpp $(PS)RemAccessBuf.cpp $(PS)Space.cpp $(PS)TraceLine.cpp $(PS)Vm.cpp \
$(PS)intersection.cpp $(PS)predictor.cpp
AlignAxis.o: $(PS)AlignAxis.cpp
$(CXX) $(CFLAGS) -c $(PS)AlignAxis.cpp
AMView.o: $(PS)AMView.cpp
$(CXX) $(CFLAGS) -c $(PS)AMView.cpp
BGroup.o: $(PS)BGroup.cpp
$(CXX) $(CFLAGS) -std=$(STD) -c $(PS)BGroup.cpp
Block.o: $(PS)Block.cpp
$(CXX) $(CFLAGS) -c $(PS)Block.cpp
CallParams.o: $(PS)CallParams.cpp
$(CXX) $(CFLAGS) -c $(PS)CallParams.cpp
CommCost.o: $(PS)CommCost.cpp
$(CXX) $(CFLAGS) -c $(PS)CommCost.cpp
DArray.o: $(PS)DArray.cpp
$(CXX) $(CFLAGS) -c $(PS)DArray.cpp
DimBound.o: $(PS)DimBound.cpp
$(CXX) $(CFLAGS) -c $(PS)DimBound.cpp
DistAxis.o: $(PS)DistAxis.cpp
$(CXX) $(CFLAGS) -c $(PS)DistAxis.cpp
Event.o: $(PS)Event.cpp
$(CXX) $(CFLAGS) -c $(PS)Event.cpp
FuncCall.o: $(PS)FuncCall.cpp
$(CXX) $(CFLAGS) -c $(PS)FuncCall.cpp
Interval.o: $(PS)Interval.cpp
$(CXX) $(CFLAGS) -c $(PS)Interval.cpp
IntervalTemplate.o: $(PS)IntervalTemplate.cpp
$(CXX) $(CFLAGS) -c $(PS)IntervalTemplate.cpp
LoopBlock.o: $(PS)LoopBlock.cpp
$(CXX) $(CFLAGS) -c $(PS)LoopBlock.cpp
LoopLS.o: $(PS)LoopLS.cpp
$(CXX) $(CFLAGS) -c $(PS)LoopLS.cpp
Ls.o: $(PS)Ls.cpp
$(CXX) $(CFLAGS) -c $(PS)Ls.cpp
ModelDArray.o: $(PS)ModelDArray.cpp
$(CXX) $(CFLAGS) -c $(PS)ModelDArray.cpp
ModelInterval.o: $(PS)ModelInterval.cpp
$(CXX) $(CFLAGS) -c $(PS)ModelInterval.cpp
ModelIO.o: $(PS)ModelIO.cpp
$(CXX) $(CFLAGS) -c $(PS)ModelIO.cpp
ModelMPS_AM.o: $(PS)ModelMPS_AM.cpp
$(CXX) $(CFLAGS) -c $(PS)ModelMPS_AM.cpp
ModelParLoop.o: $(PS)ModelParLoop.cpp
$(CXX) $(CFLAGS) -c $(PS)ModelParLoop.cpp
ModelReduct.o: $(PS)ModelReduct.cpp
$(CXX) $(CFLAGS) -c $(PS)ModelReduct.cpp
ModelRegular.o: $(PS)ModelRegular.cpp
$(CXX) $(CFLAGS) -c $(PS)ModelRegular.cpp
ModelRemAccess.o: $(PS)ModelRemAccess.cpp
$(CXX) $(CFLAGS) -c $(PS)ModelRemAccess.cpp
ModelShadow.o: $(PS)ModelShadow.cpp
$(CXX) $(CFLAGS) -c $(PS)ModelShadow.cpp
ParLoop.o: $(PS)ParLoop.cpp
$(CXX) $(CFLAGS) -c $(PS)ParLoop.cpp
ParseString.o: $(PS)ParseString.cpp
$(CXX) $(CFLAGS) -c $(PS)ParseString.cpp
Processor.o: $(PS)Processor.cpp
$(CXX) $(CFLAGS) -c $(PS)Processor.cpp
Ps.o: $(PS)Ps.cpp
$(CXX) $(CFLAGS) -c $(PS)Ps.cpp
RedGroup.o: $(PS)RedGroup.cpp
$(CXX) $(CFLAGS) -c $(PS)RedGroup.cpp
RedVar.o: $(PS)RedVar.cpp
$(CXX) $(CFLAGS) -c $(PS)RedVar.cpp
RemAccessBuf.o: $(PS)RemAccessBuf.cpp
$(CXX) $(CFLAGS) -c $(PS)RemAccessBuf.cpp
Space.o: $(PS)Space.cpp
$(CXX) $(CFLAGS) -c $(PS)Space.cpp
TraceLine.o: $(PS)TraceLine.cpp
$(CXX) $(CFLAGS) -c $(PS)TraceLine.cpp
Vm.o: $(PS)Vm.cpp
$(CXX) $(CFLAGS) -c $(PS)Vm.cpp
intersection.o: $(PS)intersection.cpp
$(CXX) $(CFLAGS) -c $(PS)intersection.cpp
predictor.o: $(PS)predictor.cpp
$(CXX) $(CFLAGS) -c $(PS)predictor.cpp
adler32.o: $(PS)adler32.c
$(CC) $(CFLAGS) -c $(PS)adler32.c
compress.o: $(PS)compress.c
$(CC) $(CFLAGS) -c $(PS)compress.c
crc32.o: $(PS)crc32.c
$(CC) $(CFLAGS) -c $(PS)crc32.c
deflate.o: $(PS)deflate.c
$(CC) $(CFLAGS) -c $(PS)deflate.c
gzio.o: $(PS)gzio.c
$(CC) $(CFLAGS) -c $(PS)gzio.c
infblock.o: $(PS)infblock.c
$(CC) $(CFLAGS) -c $(PS)infblock.c
infcodes.o: $(PS)infcodes.c
$(CC) $(CFLAGS) -c $(PS)infcodes.c
inffast.o: $(PS)inffast.c
$(CC) $(CFLAGS) -c $(PS)inffast.c
inflate.o: $(PS)inflate.c
$(CC) $(CFLAGS) -c $(PS)inflate.c
inftrees.o: $(PS)inftrees.c
$(CC) $(CFLAGS) -c $(PS)inftrees.c
infutil.o: $(PS)infutil.c
$(CC) $(CFLAGS) -c $(PS)infutil.c
trees.o: $(PS)trees.c
$(CC) $(CFLAGS) -c $(PS)trees.c
uncompr.o: $(PS)uncompr.c
$(CC) $(CFLAGS) -c $(PS)uncompr.c
zutil.o: $(PS)zutil.c
$(CC) $(CFLAGS) -c $(PS)zutil.c
$(LIBDIR)/libPred.a: $(PRED_OBJ_C) $(PRED_OBJ_CPP)
ar qc $(LIBDIR)/libPred.a $(PRED_OBJ_C) $(PRED_OBJ_CPP)
#Make SAGE++
libSage++.o: $(SAGE_SRC_DIR)libSage++.cpp $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def $(LIB_INCL)/libSage++.h
$(CXX) $(CFLAGS) -c $(SAGE_SRC_DIR)libSage++.cpp -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
$(LIBDIR)/libSage++.a: libSage++.o
ar qc $(LIBDIR)/libSage++.a libSage++.o
#Make SAGE newsrc
low_level.o: $(SAGE_SRC_NEW)low_level.c $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_NEW)low_level.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
unparse.o: $(SAGE_SRC_NEW)unparse.c $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def $(LIB_INCL)/unparse.def $(LIB_INCL)/unparseC++.def
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_NEW)unparse.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
annotate.tab.o: $(SAGE_SRC_NEW)annotate.tab.c $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_NEW)annotate.tab.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
comments.o: $(SAGE_SRC_NEW)comments.c $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_NEW)comments.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
toolsann.o: $(SAGE_SRC_NEW)toolsann.c $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_NEW)toolsann.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
$(LIBDIR)/SageNewSrc.a: low_level.o unparse.o annotate.tab.o comments.o toolsann.o $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def
ar qc $(LIBDIR)/SageNewSrc.a low_level.o unparse.o annotate.tab.o comments.o toolsann.o
#Make SAGE oldsrc
OLD_SRC_OBJS = anal_ind.o db.o db_unp.o db_unp_vpc.o dbutils.o garb_coll.o glob_anal.o ker_fun.o \
list.o make_nodes.o mod_ref.o ndeps.o readnodes.o sets.o setutils.o symb_alg.o writenodes.o
H = $(SAGE_INCL_DIR)
anal_ind.o: $(SAGE_SRC_OLD)anal_ind.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)anal_ind.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
db.o: $(SAGE_SRC_OLD)db.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)db.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
db_unp.o: $(SAGE_SRC_OLD)db_unp.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)db_unp.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
db_unp_vpc.o: $(SAGE_SRC_OLD)db_unp_vpc.c $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/db.h $(H)/vparse.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)db_unp_vpc.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
dbutils.o: $(SAGE_SRC_OLD)dbutils.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)dbutils.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
garb_coll.o: $(SAGE_SRC_OLD)garb_coll.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)garb_coll.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
glob_anal.o: $(SAGE_SRC_OLD)glob_anal.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)glob_anal.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
ker_fun.o: $(SAGE_SRC_OLD)ker_fun.c $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)ker_fun.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
list.o: $(SAGE_SRC_OLD)list.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/list.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)list.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
make_nodes.o: $(SAGE_SRC_OLD)make_nodes.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)make_nodes.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
mod_ref.o: $(SAGE_SRC_OLD)mod_ref.c $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/vparse.h $(H)/db.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)mod_ref.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
ndeps.o: $(SAGE_SRC_OLD)ndeps.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)ndeps.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
readnodes.o: $(SAGE_SRC_OLD)readnodes.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/dep_str.h $(H)/dep.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)readnodes.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
sets.o: $(SAGE_SRC_OLD)sets.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)sets.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
setutils.o: $(SAGE_SRC_OLD)setutils.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)setutils.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
symb_alg.o: $(SAGE_SRC_OLD)symb_alg.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)symb_alg.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
writenodes.o: $(SAGE_SRC_OLD)writenodes.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/dep_str.h $(H)/dep.h
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)writenodes.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
$(LIBDIR)/SageOldSrc.a: $(OLD_SRC_OBJS)
ar qc $(LIBDIR)/SageOldSrc.a $(OLD_SRC_OBJS)
#Make Parser
PARSER_OBJS = cftn.o errors.o hash.o init.o lexfdvm.o lists.o misc.o stat.o types.o gram1.tab.o sym.o low_hpf.o unparse_hpf.o
$(BINDIR)/Parser: $(PARSER_OBJS) $(LIBDIR)/SageOldSrc.a
$(CXX) -o $(BINDIR)/Parser $(PARSER_OBJS) $(LIBDIR)/SageOldSrc.a
cftn.o: $(PARSER_BASE_DIR)cftn.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)cftn.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
errors.o: $(PARSER_BASE_DIR)errors.c $(H)/defs.h $(H)/tag $(H)/symb.h $(DVMINCLUDE)/extern.h $(H)/db.h $(H)/bif.h $(H)/ll.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)errors.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
hash.o: $(PARSER_BASE_DIR)hash.c $(H)/defs.h $(H)/symb.h $(H)/defines.h $(DVMINCLUDE)/extern.h $(H)/db.h $(H)/bif.h $(H)/ll.h $(H)/sets.h $(H)/tag
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)hash.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
init.o: $(PARSER_BASE_DIR)init.c $(DVMINCLUDE)/inc.h $(H)/defs.h $(H)/bif.h $(H)/defines.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/db.h $(H)/tag
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)init.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
lexfdvm.o: $(PARSER_BASE_DIR)lexfdvm.c $(DVMINCLUDE)/extern.h
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)lexfdvm.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
lists.o: $(PARSER_BASE_DIR)lists.c $(H)/defs.h $(H)/ll.h $(H)/symb.h $(H)/bif.h
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)lists.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
misc.o: $(PARSER_BASE_DIR)misc.c $(H)/defs.h $(H)/tag $(H)/defines.h $(H)/db.h $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)misc.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
stat.o: $(PARSER_BASE_DIR)stat.c $(H)/defs.h $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/defines.h $(DVMINCLUDE)/extern.h
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)stat.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
sym.o: $(PARSER_BASE_DIR)sym.c $(H)/defs.h $(H)/tag $(H)/symb.h $(H)/defines.h $(H)/bif.h $(DVMINCLUDE)/extern.h $(H)/db.h $(H)/ll.h $(H)/sets.h $(DVMINCLUDE)/fdvm.h
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)sym.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
types.o: $(PARSER_BASE_DIR)types.c $(H)/defs.h $(H)/ll.h $(H)/symb.h
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)types.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
low_hpf.o: $(PARSER_BASE_DIR)low_hpf.c $(DVMINCLUDE)/dvm_tag.h $(TOOLBOX_HDR)
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)low_hpf.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
unparse_hpf.o: $(PARSER_BASE_DIR)unparse_hpf.c $(DVMINCLUDE)/dvm_tag.h $(TOOLBOX_HDR) $(DVMINCLUDE)/unparse.hpf
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)unparse_hpf.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
gram1.tab.o: $(PARSER_BASE_DIR)gram1.tab.c
$(CC) $(CFLAGS) -c -DSYS5 -DYYDEBUG $(PARSER_BASE_DIR)gram1.tab.c -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
#Make Inliner
$(BINDIR)/Inliner: inl_exp.o inliner.o hlp.o $(LIBDIR)/libSage++.a $(LIBDIR)/SageNewSrc.a $(LIBDIR)/SageOldSrc.a
$(CXX) -o $(BINDIR)/Inliner inl_exp.o inliner.o hlp.o $(LIBDIR)/libSage++.a $(LIBDIR)/SageNewSrc.a $(LIBDIR)/SageOldSrc.a
inl_exp.o: $(INLINER_BASE_DIR)inl_exp.cpp $(INLINER_BASE_DIR)inline.h
$(CXX) $(CFLAGS) -std=$(STD) -c $(INLINER_BASE_DIR)inl_exp.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
inliner.o: $(INLINER_BASE_DIR)inliner.cpp $(INLINER_BASE_DIR)inline.h
$(CXX) $(CFLAGS) -std=$(STD) -c $(INLINER_BASE_DIR)inliner.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
hlp.o: $(INLINER_BASE_DIR)hlp.cpp $(INLINER_BASE_DIR)inline.h
$(CXX) $(CFLAGS) -std=$(STD) -c $(INLINER_BASE_DIR)hlp.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
#Make Sapfor
SAPFOR_OBJ = private_analyzer.o utils.o SgUtils.o Sapfor.o CorrectVarDecl.o IncludeChecker.o LoopChecker.o ParRegions.o \
enddo_loop_converter.o array_assign_to_loop.o allocations_prepoc.o directive_creator.o insert_directive.o loop_analyzer.o spf_directive_preproc.o \
graph_loops.o graph_loops_base.o graph_calls.o expr_transform.o CreateDistributionDirs.o DvmhDirective.o DvmhDirectiveBase.o DirectiveAnalyzer.o \
acc_analyzer.o acc_data.o calls.o acc_utilities.o directive_parser.o GraphCSR.o Distribution.o Cycle.o \
annotationDriver.o arrayRef.o computeInducVar.o constanteProp.o controlFlow.o defUse.o dependence.o depGraph.o \
depInterface.o flowAnalysis.o intrinsic.o invariant.o loopTransform.o set.o \
add-assert.o affine.o cover.o ddomega.o ddomega-build.o ddomega-use.o debug.o ip.o kill.o refine.o sagedriver.o \
dep_analyzer.o remote_access.o VerifySageStructures.o loop_transform.o PredictScheme.o control_flow_graph_part.o \
shadow.o private_arrays_breeder.o resolve_par_reg_conflicts.o loops_splitter.o loops_combiner.o CreateInterTree.o gcov_info.o gCov_parser.o \
graph_calls_base.o directive_creator_base.o PredictorModel.o createParallelRegions.o \
expand_extract_reg.o RationalNum.o Array.o DvmhRegionInserter.o uniq_call_chain_dup.o
$(BINDIR)/Sapfor: $(SAPFOR_OBJ) $(LIBDIR)/libSage++.a $(LIBDIR)/SageNewSrc.a $(LIBDIR)/SageOldSrc.a
$(CXX) -fopenmp -o $(BINDIR)/Sapfor $(SAPFOR_OBJ) $(LIBDIR)/libSage++.a $(LIBDIR)/SageNewSrc.a $(LIBDIR)/SageOldSrc.a $(LIBDIR)/libPred.a
expand_extract_reg.o: $(REPO_SPF_BASE)ParallelizationRegions/expand_extract_reg.cpp $(REPO_SPF_BASE)ParallelizationRegions/expand_extract_reg.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)ParallelizationRegions/expand_extract_reg.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) $(TR_LIB_INC)
createParallelRegions.o: $(REPO_SPF_BASE)DynamicAnalysis/createParallelRegions.cpp $(REPO_SPF_BASE)DynamicAnalysis/createParallelRegions.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)DynamicAnalysis/createParallelRegions.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
gcov_info.o: $(REPO_SPF_BASE)DynamicAnalysis/gcov_info.cpp $(REPO_SPF_BASE)DynamicAnalysis/gcov_info.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)DynamicAnalysis/gcov_info.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
gCov_parser.o: $(REPO_SPF_BASE)DynamicAnalysis/gCov_parser.cpp $(REPO_SPF_BASE)DynamicAnalysis/gCov_parser_func.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)DynamicAnalysis/gCov_parser.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
CreateInterTree.o: $(REPO_SPF_BASE)CreateInterTree/CreateInterTree.cpp $(REPO_SPF_BASE)CreateInterTree/CreateInterTree.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)CreateInterTree/CreateInterTree.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
RationalNum.o: $(REPO_SPF_BASE)Utils/RationalNum.cpp $(REPO_SPF_BASE)Utils/RationalNum.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Utils/RationalNum.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
utils.o: $(REPO_SPF_BASE)Utils/utils.cpp $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)Utils/utils.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Utils/utils.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
SgUtils.o: $(REPO_SPF_BASE)Utils/SgUtils.cpp $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)Utils/utils.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Utils/SgUtils.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
directive_parser.o: $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.cpp $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h $(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
Sapfor.o: $(REPO_SPF_BASE)Sapfor.cpp $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)LoopConverter/enddo_loop_converter.h \
$(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h $(REPO_SPF_BASE)GraphCall/graph_calls.h $(REPO_SPF_BASE)GraphLoop/graph_loops.h \
$(REPO_SPF_BASE)DirectiveAnalyzer/DirectiveAnalyzer.h $(REPO_SPF_BASE)VerificationCode/verifications.h $(REPO_SPF_BASE)Distribution/CreateDistributionDirs.h \
$(REPO_SPF_BASE)PrivateAnalyzer/private_analyzer.h $(REPO_SPF_BASE)Sapfor.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Sapfor.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) $(TR_LIB_INC)
CorrectVarDecl.o: $(REPO_SPF_BASE)VerificationCode/CorrectVarDecl.cpp $(REPO_SPF_BASE)VerificationCode/verifications.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)VerificationCode/CorrectVarDecl.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
IncludeChecker.o: $(REPO_SPF_BASE)VerificationCode/IncludeChecker.cpp $(REPO_SPF_BASE)VerificationCode/verifications.h $(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)Distribution/DvmhDirective.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)VerificationCode/IncludeChecker.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
LoopChecker.o: $(REPO_SPF_BASE)VerificationCode/LoopChecker.cpp $(REPO_SPF_BASE)VerificationCode/verifications.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)VerificationCode/LoopChecker.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
VerifySageStructures.o: $(REPO_SPF_BASE)VerificationCode/VerifySageStructures.cpp $(REPO_SPF_BASE)VerificationCode/verifications.h $(REPO_SPF_BASE)Utils/utils.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)VerificationCode/VerifySageStructures.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
private_analyzer.o: $(REPO_SPF_BASE)PrivateAnalyzer/private_analyzer.cpp $(REPO_SPF_BASE)PrivateAnalyzer/private_analyzer.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)PrivateAnalyzer/private_analyzer.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
acc_analyzer.o: $(REPO_FDVM_BASE)fdvm/acc_analyzer.cpp $(REPO_FDVM_BASE)include/acc_analyzer.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_FDVM_BASE)fdvm/acc_analyzer.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(REPO_SPF_BASE)
acc_data.o: $(REPO_FDVM_BASE)fdvm/acc_data.cpp
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_FDVM_BASE)fdvm/acc_data.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
acc_utilities.o: $(REPO_FDVM_BASE)fdvm/acc_utilities.cpp
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_FDVM_BASE)fdvm/acc_utilities.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
calls.o: $(REPO_FDVM_BASE)fdvm/calls.cpp
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_FDVM_BASE)fdvm/calls.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
ParRegions.o: $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.cpp $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
resolve_par_reg_conflicts.o: $(REPO_SPF_BASE)ParallelizationRegions/resolve_par_reg_conflicts.cpp $(REPO_SPF_BASE)ParallelizationRegions/resolve_par_reg_conflicts.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)ParallelizationRegions/resolve_par_reg_conflicts.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
enddo_loop_converter.o: $(REPO_SPF_BASE)LoopConverter/enddo_loop_converter.cpp $(REPO_SPF_BASE)LoopConverter/enddo_loop_converter.h $(REPO_SPF_BASE)Utils/errors.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/enddo_loop_converter.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
array_assign_to_loop.o: $(REPO_SPF_BASE)LoopConverter/array_assign_to_loop.cpp $(REPO_SPF_BASE)LoopConverter/array_assign_to_loop.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/array_assign_to_loop.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
uniq_call_chain_dup.o: $(REPO_SPF_BASE)LoopConverter/uniq_call_chain_dup.cpp $(REPO_SPF_BASE)LoopConverter/uniq_call_chain_dup.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/uniq_call_chain_dup.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
loop_transform.o: $(REPO_SPF_BASE)LoopConverter/loop_transform.cpp $(REPO_SPF_BASE)LoopConverter/loop_transform.h $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)GraphLoop/graph_loops.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/loop_transform.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) $(TR_LIB_INC)
shadow.o: $(REPO_SPF_BASE)LoopAnalyzer/shadow.cpp $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/shadow.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) $(TR_LIB_INC)
allocations_prepoc.o: $(REPO_SPF_BASE)LoopAnalyzer/allocations_prepoc.cpp $(REPO_SPF_BASE)Utils/utils.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/allocations_prepoc.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
directive_creator.o: $(REPO_SPF_BASE)LoopAnalyzer/directive_creator.cpp $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.h \
$(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Distribution.h \
$(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h $(REPO_SPF_BASE)Utils/utils.h \
$(REPO_SPF_BASE)Sapfor.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/directive_creator.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
$(TR_LIB_INC)
directive_creator_base.o: $(REPO_SPF_BASE)LoopAnalyzer/directive_creator_base.cpp $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.h \
$(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Distribution.h \
$(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h $(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)LoopAnalyzer/directive_creator.h \
$(REPO_SPF_BASE)Sapfor.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/directive_creator_base.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) $(TR_LIB_INC)
insert_directive.o: $(REPO_SPF_BASE)LoopAnalyzer/insert_directive.cpp $(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h \
$(REPO_SPF_BASE)Distribution/Distribution.h $(REPO_SPF_BASE)Distribution/DvmhDirective.h $(REPO_SPF_BASE)Utils/errors.h \
$(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h $(REPO_SPF_BASE)Utils/utils.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/insert_directive.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
loop_analyzer.o: $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.cpp $(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h \
$(REPO_SPF_BASE)Distribution/Distribution.h $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.h $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h \
$(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h $(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)GraphCall/graph_calls.h $(REPO_SPF_BASE)ExpressionTransform/expr_transform.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
remote_access.o: $(REPO_SPF_BASE)LoopAnalyzer/remote_access.cpp $(REPO_SPF_BASE)Distribution/Arrays.h \
$(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h \
$(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)GraphCall/graph_calls.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/remote_access.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
dep_analyzer.o: $(REPO_SPF_BASE)LoopAnalyzer/dep_analyzer.cpp $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h $(REPO_SPF_BASE)Utils/utils.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/dep_analyzer.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
spf_directive_preproc.o: $(REPO_SPF_BASE)LoopAnalyzer/spf_directive_preproc.cpp
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/spf_directive_preproc.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
graph_loops.o: $(REPO_SPF_BASE)GraphLoop/graph_loops.cpp $(REPO_SPF_BASE)GraphLoop/graph_loops.h $(REPO_SPF_BASE)GraphCall/graph_calls.h \
$(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Distribution.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)GraphLoop/graph_loops.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
graph_loops_base.o: $(REPO_SPF_BASE)GraphLoop/graph_loops_base.cpp $(REPO_SPF_BASE)GraphLoop/graph_loops.h $(REPO_SPF_BASE)GraphCall/graph_calls.h \
$(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Distribution.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)GraphLoop/graph_loops_base.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
PredictScheme.o: $(REPO_SPF_BASE)Predictor/PredictScheme.cpp $(REPO_SPF_BASE)Predictor/PredictScheme.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Predictor/PredictScheme.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
PredictorModel.o: $(REPO_SPF_BASE)Predictor/PredictorModel.cpp $(REPO_SPF_BASE)Predictor/PredictorModel.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Predictor/PredictorModel.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
graph_calls.o: $(REPO_SPF_BASE)GraphCall/graph_calls.cpp $(REPO_SPF_BASE)GraphLoop/graph_loops.h $(REPO_SPF_BASE)GraphCall/graph_calls.h $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)GraphCall/graph_calls.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
graph_calls_base.o: $(REPO_SPF_BASE)GraphCall/graph_calls_base.cpp $(REPO_SPF_BASE)GraphCall/graph_calls_func.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)GraphCall/graph_calls_base.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
expr_transform.o: $(REPO_SPF_BASE)ExpressionTransform/expr_transform.cpp $(REPO_FDVM_BASE)include/acc_analyzer.h $(REPO_SPF_BASE)ExpressionTransform/expr_transform.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)ExpressionTransform/expr_transform.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
control_flow_graph_part.o: $(REPO_SPF_BASE)ExpressionTransform/control_flow_graph_part.cpp $(REPO_FDVM_BASE)include/acc_analyzer.h $(REPO_SPF_BASE)ExpressionTransform/expr_transform.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)ExpressionTransform/control_flow_graph_part.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
CreateDistributionDirs.o: $(REPO_SPF_BASE)Distribution/CreateDistributionDirs.cpp $(REPO_SPF_BASE)Distribution/Distribution.h $(REPO_SPF_BASE)Distribution/GraphCSR.h \
$(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)GraphLoop/graph_loops.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/CreateDistributionDirs.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
DvmhDirective.o: $(REPO_SPF_BASE)Distribution/DvmhDirective.cpp $(REPO_SPF_BASE)Distribution/DvmhDirective.h $(REPO_SPF_BASE)Utils/utils.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/DvmhDirective.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
DvmhDirectiveBase.o: $(REPO_SPF_BASE)Distribution/DvmhDirectiveBase.cpp $(REPO_SPF_BASE)Distribution/DvmhDirectiveBase.h $(REPO_SPF_BASE)Utils/utils.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/DvmhDirectiveBase.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
DirectiveAnalyzer.o: $(REPO_SPF_BASE)DirectiveAnalyzer/DirectiveAnalyzer.cpp $(REPO_SPF_BASE)Distribution/DvmhDirective.h $(REPO_SPF_BASE)GraphLoop/graph_loops.h \
$(REPO_SPF_BASE)DirectiveAnalyzer/DirectiveAnalyzer.h $(REPO_SPF_BASE)Utils/utils.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)DirectiveAnalyzer/DirectiveAnalyzer.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
Cycle.o: $(REPO_SPF_BASE)Distribution/Cycle.cpp $(REPO_SPF_BASE)Distribution/Cycle.h $(REPO_SPF_BASE)Distribution/DvmhDirective.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/Cycle.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
Distribution.o: $(REPO_SPF_BASE)Distribution/Distribution.cpp $(REPO_SPF_BASE)Distribution/Distribution.h $(REPO_SPF_BASE)Distribution/DvmhDirective.h \
$(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Array.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/Distribution.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
Array.o: $(REPO_SPF_BASE)Distribution/Array.cpp $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Array.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/Array.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
GraphCSR.o: $(REPO_SPF_BASE)Distribution/GraphCSR.cpp $(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/DvmhDirective.h \
$(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Array.h \
$(REPO_SPF_BASE)Distribution/Cycle.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/GraphCSR.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
annotationDriver.o: $(REPO_SPF_BASE)SageAnalysisTool/annotationDriver.cpp $(REPO_SPF_BASE)SageAnalysisTool/annotationDriver.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/annotationDriver.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
arrayRef.o: $(REPO_SPF_BASE)SageAnalysisTool/arrayRef.cpp $(REPO_SPF_BASE)SageAnalysisTool/arrayRef.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/arrayRef.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
computeInducVar.o: $(REPO_SPF_BASE)SageAnalysisTool/computeInducVar.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/computeInducVar.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
constanteProp.o: $(REPO_SPF_BASE)SageAnalysisTool/constanteProp.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/constanteProp.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
controlFlow.o: $(REPO_SPF_BASE)SageAnalysisTool/controlFlow.cpp
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/controlFlow.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
defUse.o: $(REPO_SPF_BASE)SageAnalysisTool/defUse.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/defUse.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
dependence.o: $(REPO_SPF_BASE)SageAnalysisTool/dependence.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h $(REPO_SPF_BASE)SageAnalysisTool/dependence.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/dependence.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
depGraph.o: $(REPO_SPF_BASE)SageAnalysisTool/depGraph.cpp
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/depGraph.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
depInterface.o: $(REPO_SPF_BASE)SageAnalysisTool/depInterface.cpp
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/depInterface.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
flowAnalysis.o: $(REPO_SPF_BASE)SageAnalysisTool/flowAnalysis.cpp
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/flowAnalysis.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
intrinsic.o: $(REPO_SPF_BASE)SageAnalysisTool/intrinsic.cpp $(REPO_SPF_BASE)SageAnalysisTool/intrinsic.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/intrinsic.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
invariant.o: $(REPO_SPF_BASE)SageAnalysisTool/invariant.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/invariant.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
loopTransform.o: $(REPO_SPF_BASE)SageAnalysisTool/loopTransform.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/loopTransform.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
set.o: $(REPO_SPF_BASE)SageAnalysisTool/set.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/set.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
add-assert.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/add-assert.cpp
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/add-assert.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
affine.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/affine.cpp
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/affine.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
cover.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/cover.cpp
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/cover.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
ddomega.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega.cpp
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
ddomega-build.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega-build.cpp
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega-build.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
ddomega-use.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega-use.cpp
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega-use.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
debug.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/debug.cpp
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/debug.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
ip.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ip.cpp
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ip.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
kill.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/kill.cpp
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/kill.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
refine.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/refine.cpp
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/refine.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
sagedriver.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/sagedriver.cpp
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/sagedriver.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
private_arrays_breeder.o: $(REPO_SPF_BASE)LoopConverter/private_arrays_breeder.cpp $(REPO_SPF_BASE)LoopConverter/private_arrays_breeder.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/private_arrays_breeder.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
loops_splitter.o: $(REPO_SPF_BASE)LoopConverter/loops_splitter.cpp $(REPO_SPF_BASE)LoopConverter/loops_splitter.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/loops_splitter.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
DvmhRegionInserter.o: $(REPO_SPF_BASE)DvmhRegions/DvmhRegionInserter.cpp $(REPO_SPF_BASE)DvmhRegions/DvmhRegionInserter.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)DvmhRegions/DvmhRegionInserter.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
loops_combiner.o: $(REPO_SPF_BASE)LoopConverter/loops_combiner.cpp $(REPO_SPF_BASE)LoopConverter/loops_combiner.h
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/loops_combiner.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
clean:
rm -rf *.o
cleanall:
rm -rf *.o ../_lib/*.a

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,151 @@
#pragma once
#include <string>
#include <map>
#include <set>
#include <vector>
#include "IR.h"
namespace SAPFOR
{
enum CFG_VAL : int { KILL_ALL = -1, UNINIT = -2 };
class IR_Block;
class Argument;
class Instruction;
class BasicBlock
{
static int lastNumBlock;
private:
int num;
std::vector<IR_Block*> instructions;
std::vector<BasicBlock*> next;
std::vector<BasicBlock*> prev;
//reaching definition
std::map<SAPFOR::Argument*, std::set<int>> RD_in, RD_out;
//live variables [arg -> blocks with usages]
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> live_in, live_out, live_inout;
bool addLive(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add, bool in);
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLive(bool in) const;
bool removeLive(SAPFOR::Argument* to_remove, bool in);
public:
BasicBlock() { num = lastNumBlock++; }
BasicBlock(IR_Block* item);
BasicBlock(const BasicBlock& copyFrom);
void addInstructionBeforeInstruction(IR_Block* item, Instruction* istruction);
void addInstructionInFront(IR_Block* item);
void addInstruction(IR_Block* item);
void addPrev(BasicBlock* prev_) { prev.push_back(prev_); }
void addNext(BasicBlock* next_) { next.push_back(next_); }
int removePrev(BasicBlock* removed);
int removeNext(BasicBlock* removed);
void replacePrevNext(const std::map<BasicBlock*, BasicBlock*>& oldToNew)
{
for (int z = 0; z < next.size(); ++z)
{
auto it = oldToNew.find(next[z]);
if (it == oldToNew.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
next[z] = it->second;
}
for (int z = 0; z < prev.size(); ++z)
{
auto it = oldToNew.find(prev[z]);
if (it == oldToNew.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
prev[z] = it->second;
}
}
int getNumber() const { return num; }
const std::vector<IR_Block*>& getInstructions() const { return instructions; }
const std::vector<BasicBlock*>& getNext() const { return next; }
const std::vector<BasicBlock*>& getPrev() const { return prev; }
/*
* FOR LIVE ANALYSIS
*/
bool addLiveIn(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, true); };
bool addLiveOut(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, false); };
bool removeLiveIn(SAPFOR::Argument* to_remove) { return removeLive(to_remove, true); };
bool removeLiveOut(SAPFOR::Argument* to_remove) { return removeLive(to_remove, false); };
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLiveIn() const { return getLive(true); };
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLiveOut() const { return getLive(false); };
void compressLives();
/*
* FOR REACHING DEFINITIONS
*/
void setRD_In(const std::map<Argument*, std::set<int>>& inSet) { RD_in = inSet; }
void setRD_Out(const std::map<Argument*, std::set<int>>& outSet) { RD_out = outSet; }
const std::map<Argument*, std::set<int>>& getRD_In() const { return RD_in; }
const std::map<Argument*, std::set<int>>& getRD_Out() const { return RD_out; }
std::map<Argument*, std::set<int>>& getModRD_In() { return RD_in; }
std::map<Argument*, std::set<int>>& getModRD_Out() { return RD_out; }
~BasicBlock();
};
struct CFG_Settings
{
bool atLeastOneIterInLoop = false;
bool withRD = true;
bool withRegisters = false;
bool withSPF = false;
bool withDVM = false;
bool withCallsInBlocks = false; // separate each F_CALL to own BasicBlock
bool withCallFrom = true;
explicit CFG_Settings(int) { }
explicit CFG_Settings(bool atLeastOneIterInLoop = false, bool withRD = true, bool withRegisters = false,
bool withDVM = false, bool withSPF = false, bool withCallsInBlocks = false, bool withCallFrom = true) :
atLeastOneIterInLoop(atLeastOneIterInLoop), withRD(withRD), withRegisters(withRegisters), withDVM(withDVM), withSPF(withSPF),
withCallsInBlocks(withCallsInBlocks), withCallFrom(withCallFrom)
{ }
};
}
std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> buildCFG(const std::map<std::string, CommonBlock*>& commonBlocks, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, const SAPFOR::CFG_Settings settings);
std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> buildCFGforCurrentFunc(SgStatement* stmt, SAPFOR::CFG_Settings settings, const std::map<std::string, CommonBlock*>& commonBlocks, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
std::vector<std::pair<const Variable*, CommonBlock*>> getCommonsByFunction(SgFile* file, SgStatement* function, const std::map<std::string, CommonBlock*>& commonBlocks);
std::vector<SAPFOR::IR_Block*> getAllIR(const std::vector<SAPFOR::BasicBlock*>& blocks);
void dumpCFG(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& blocks, bool withRD);
std::vector<std::set<FuncInfo*>> groupByCallDependencies(const std::map<FuncInfo*, std::set<FuncInfo*>>& callDeps, std::vector<std::set<FuncInfo*>>& scc);
template<typename T>
bool intersectAndAdd(std::set<T>& s1, const std::set<T>& s2);
void buildGenKillForCFG(const std::vector<SAPFOR::BasicBlock*>& CFG,
const std::map<std::string, FuncInfo*>& funcByName,
const std::map<FuncInfo*, std::map<SAPFOR::Argument*, std::set<int>>>& outForFunc,
std::map<SAPFOR::BasicBlock*, std::map<SAPFOR::Argument*, std::set<int>>>& gen,
std::map<SAPFOR::BasicBlock*, std::map<SAPFOR::Argument*, std::set<int>>>& kill,
std::map<SAPFOR::Instruction*, std::map<SAPFOR::Argument*, std::set<int>>>* genForIR,
std::map<SAPFOR::Instruction*, std::map<SAPFOR::Argument*, std::set<int>>>* killForIR,
std::map<SAPFOR::BasicBlock*, std::set<SAPFOR::Argument*>>& notInitedGlobals,
const SAPFOR::CFG_Settings settings);
static inline void deleteCFG(std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& cfg)
{
for (auto& byFunc : cfg)
{
for (auto& block : byFunc.second)
delete block;
byFunc.second.clear();
}
cfg.clear();
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include "data_flow.h"
#include <vector>
#include <set>
#include <algorithm>
#include "../../Utils/SgUtils.h"
#include "../CFGraph.h"
#include "../IR.h"
template <class NodeType>
class BackwardDataFlowAnalysis : public DataFlowAnalysis<NodeType>
{
std::vector<SAPFOR::BasicBlock*> reorderSequence(const std::vector<SAPFOR::BasicBlock*>& blocks,
const std::set<SAPFOR::BasicBlock*> back_edge_sources);
public:
void fit(const std::vector<SAPFOR::BasicBlock*>& blocks);
};
#include "backward_data_flow_impl.h"

View File

@@ -0,0 +1,103 @@
#pragma once
#include "backward_data_flow.h"
#include <vector>
#include <set>
#include <algorithm>
#include "../../Utils/SgUtils.h"
#include "../CFGraph.h"
#include "../IR.h"
#include "../RD_subst.h"
/* Note: this file should be included in backward_data_flow.h to provide template definitions */
// minimizes the number of blocks beween the ends of back edges
template <class NodeType>
std::vector<SAPFOR::BasicBlock*>
BackwardDataFlowAnalysis<NodeType>::reorderSequence(const std::vector<SAPFOR::BasicBlock*>& blocks,
const std::set<SAPFOR::BasicBlock*> back_edge_sources)
{
std::vector<SAPFOR::BasicBlock*> res = { };
auto blocks_end = blocks.rend();
for (auto it = blocks.rbegin(); it < blocks_end; it++)
{
SAPFOR::BasicBlock* curr = *it;
auto res_end = res.end();
auto inserter = res.begin();
if (back_edge_sources.count(curr) == 0)
{
auto curr_next_begin = curr->getNext().begin();
auto curr_next_end = curr->getNext().end();
while (inserter < res_end && std::find(curr_next_begin, curr_next_end, *inserter) == curr_next_end)
inserter++;
}
res.insert(inserter, curr);
}
return res;
}
template <class NodeType>
void BackwardDataFlowAnalysis<NodeType>::fit(const std::vector<SAPFOR::BasicBlock*>& blocks)
{
std::set<std::pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>> back_edges = {};
bool returned = false;
std::map<SAPFOR::BasicBlock*, std::set<SAPFOR::BasicBlock*>> back_edges_by_src;
auto blocks_sorted = sortCfgNodes(blocks, &back_edges);
std::set<SAPFOR::BasicBlock*> back_edge_sources;
for (auto& edge : back_edges)
{
back_edges_by_src[edge.first].insert(edge.second);
back_edge_sources.insert(edge.first);
}
back_edges.clear();
blocks_sorted = reorderSequence(blocks_sorted, back_edge_sources);
back_edge_sources.clear();
std::reverse(blocks_sorted.begin(), blocks_sorted.end());
this->nodes.clear();
std::map<SAPFOR::BasicBlock*, NodeType*> node_by_block;
for (auto block : blocks_sorted)
{
NodeType* node = this->createNode(block);
this->nodes.push_back(node);
node_by_block[block] = node;
}
int nodes_size = this->nodes.size();
for (int i = 0; i < nodes_size; i++)
{
NodeType* node = this->nodes[i];
auto back_edges_by_src_it = back_edges_by_src.find(node->getBlock());
if (back_edges_by_src_it != back_edges_by_src.end())
{
// This node is a source for back edge
for (auto dest : back_edges_by_src_it->second)
{
auto node_by_block_it = node_by_block.find(dest);
if (node_by_block_it != node_by_block.end())
node_by_block_it->second->getRollback().insert(i);
}
}
for (auto next : node->getBlock()->getNext())
{
auto node_by_block_it = node_by_block.find(next);
if (node_by_block_it != node_by_block.end())
node->getPrevBlocks().insert(node_by_block_it->second);
}
}
}

View File

@@ -0,0 +1,68 @@
#pragma once
#include<vector>
#include<set>
#include "../../Utils/SgUtils.h"
#include "../CFGraph.h"
#include "../IR.h"
enum class DATA_FLOW_UPD_STATUS { NO_CHANGE = 0, PROPAGATED, GENERATED };
template <class DataType>
class DataFlowAnalysisNode {
static const int CNT_NOTINIT = 0;
int in_cnt = CNT_NOTINIT, out_cnt = CNT_NOTINIT;
std::set<int> rollback;
std::set<DataFlowAnalysisNode<DataType>*> prev_blocks;
SAPFOR::BasicBlock* bb;
public:
DataFlowAnalysisNode();
void doStep();
virtual DataType getIn() = 0;
virtual DataType getOut() = 0;
virtual bool addIn(const DataType& data) = 0;
virtual bool addOut(const DataType& data) = 0;
virtual bool updateState() { return false; }
virtual DATA_FLOW_UPD_STATUS forwardData(const DataType& data) = 0;
bool newerThan(const DataFlowAnalysisNode<DataType>* block) const { return out_cnt > block->in_cnt; }
int getInCnt() { return in_cnt; }
int getOutCnt() { return out_cnt; }
void setInCnt(int cnt) { in_cnt = cnt; }
void setOutCnt(int cnt) { out_cnt = cnt; }
static int getStartCounter() { return CNT_NOTINIT; }
std::set<int>& getRollback() { return rollback; }
std::set<DataFlowAnalysisNode<DataType>*>& getPrevBlocks() { return prev_blocks; }
SAPFOR::BasicBlock* getBlock() { return bb; }
void setBlock(SAPFOR::BasicBlock* b) { bb = b; }
};
template <class NodeType>
class DataFlowAnalysis {
protected:
std::vector<NodeType*> nodes;
virtual NodeType* createNode(SAPFOR::BasicBlock* block) = 0;
public:
virtual void fit(const std::vector<SAPFOR::BasicBlock*>& blocks) = 0;
void analyze();
const std::vector<NodeType*>& getNodes() { return nodes; }
~DataFlowAnalysis();
};
#include "data_flow_impl.h"

View File

@@ -0,0 +1,112 @@
#pragma once
#include "data_flow.h"
#include<vector>
#include<set>
#include "../../Utils/SgUtils.h"
#include "../CFGraph.h"
#include "../IR.h"
/* Note: this file should be included in data_flow.h to provide template definitions */
/* definitions for DataFlowAnalysisNode class */
template <class DataType>
const int DataFlowAnalysisNode<DataType>::CNT_NOTINIT;
template <class DataType>
DataFlowAnalysisNode<DataType>::DataFlowAnalysisNode()
{
getRollback() = {};
prev_blocks = {};
}
template <class DataType>
void DataFlowAnalysisNode<DataType>::doStep()
{
int in_max_cnt = CNT_NOTINIT, out_max_cnt = CNT_NOTINIT;
bool uniq_change = updateState();
for (auto next : prev_blocks)
{
if (in_cnt < next->out_cnt)
{
if (next->out_cnt > in_max_cnt)
in_max_cnt = next->out_cnt;
const auto& byOut = next->getOut();
bool inserted = addIn( byOut);
if (inserted)
{
auto status = forwardData(byOut);
inserted = status != DATA_FLOW_UPD_STATUS::NO_CHANGE;
if (inserted && next->out_cnt > out_max_cnt)
out_max_cnt = next->out_cnt;
uniq_change |= status == DATA_FLOW_UPD_STATUS::GENERATED;
}
}
}
uniq_change |= (out_cnt == CNT_NOTINIT);
if (out_max_cnt != CNT_NOTINIT)
out_cnt = out_max_cnt;
if (in_max_cnt != CNT_NOTINIT)
in_cnt = in_max_cnt;
// TODO: fix counter overflow
if (uniq_change)
{
out_cnt++;
in_cnt++;
}
}
/* definitions for DataFlowAnalysis class */
template <class NodeType>
void DataFlowAnalysis<NodeType>::analyze()
{
auto curr = 0;
auto stop = nodes.size();
while (curr != stop)
{
auto curr_bb = nodes[curr];
curr_bb->doStep();
const auto& jumps = curr_bb->getRollback();
if (jumps.size() != 0)
{
bool jump = false;
for (const auto& jump_to : jumps)
{
if (curr_bb->newerThan(nodes[jump_to]))
{
jump = true;
curr = jump_to;
break;
}
}
if (jump)
continue;
}
curr++;
}
}
template <class NodeType>
DataFlowAnalysis<NodeType>::~DataFlowAnalysis()
{
for (NodeType* node : nodes)
delete node;
nodes.clear();
}

1752
Sapfor/_src/CFGraph/IR.cpp Normal file

File diff suppressed because it is too large Load Diff

349
Sapfor/_src/CFGraph/IR.h Normal file
View File

@@ -0,0 +1,349 @@
#pragma once
#include <string>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include "CFGraph.h"
#include "../Utils/CommonBlock.h"
namespace SAPFOR
{
struct CFG_Settings;
enum class CFG_OP { NONE, ASSIGN, POINTER_ASS, LOAD, STORE, REC_REF_LOAD, REC_REF_STORE, REF, PARAM, IO_PARAM, RANGE, ENTRY, REC_REF,
ADD, MULT, DIV, SUBT, UN_ADD, UN_MINUS, POW, CONCAT, CAST,
JUMP, JUMP_IF,
GE, LE, GT, LT, EQ, NEQV, EQV, EMPTY, OR, AND, NOT,
F_CALL, EXIT,
DVM_DIR, SPF_DIR };
enum class CFG_ARG_TYPE { NONE, REG, VAR, ARRAY, CONST, FUNC, LAB, INSTR, CONST_STR, RECORD, CONSTR_REF };
enum class CFG_MEM_TYPE { NONE_, COMMON_, SAVE_, LOCAL_, MODULE_, FUNC_RES_, FUNC_PARAM_, FILED_ };
static std::vector<std::string> CFG_OP_S = { "--", " = ", " => ", "LOAD ", "STORE ", "LOAD_REF ", "STORE_REF ", "REF ", "PARAM ", "IO_PARAM ", "RANGE ", "ENTRY ", "->",
" + ", " * ", " / ", " - ", " + ", "-", " ** ", " // ", "CAST ",
"GOTO ", "IF_FALSE ",
" >= ", " <= ", " > " , " < ", " == ", " != ", " eqv ", "CONTINUE", " || ", " && ", " ! ",
"F_CALL ", "EXIT ",
" ", " " };
class Argument
{
static int lastNumArg;
private:
int number;
CFG_ARG_TYPE type;
CFG_MEM_TYPE mType;
std::string value;
public:
Argument() : number(lastNumArg++), type(CFG_ARG_TYPE::NONE), value(""), mType(CFG_MEM_TYPE::NONE_) { }
Argument(CFG_ARG_TYPE type, CFG_MEM_TYPE mType) : number(lastNumArg++), type(type), mType(mType), value("") { }
Argument(CFG_ARG_TYPE type, CFG_MEM_TYPE mType, const std::string& value) : number(lastNumArg++), type(type), mType(mType), value(value) { }
Argument(CFG_ARG_TYPE type, CFG_MEM_TYPE mType, const std::string& value, int num) : number(num), type(type), mType(mType), value(value) { }
Argument(CFG_ARG_TYPE type, const std::string& value) : number(lastNumArg++), type(type), mType(CFG_MEM_TYPE::NONE_), value(value)
{
if (type != CFG_ARG_TYPE::INSTR && type == CFG_ARG_TYPE::LAB &&
type != CFG_ARG_TYPE::NONE && type != CFG_ARG_TYPE::FUNC)
{
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}
void setType(CFG_ARG_TYPE newType) { type = newType; }
CFG_ARG_TYPE getType() const { return type; }
void setMemType(CFG_MEM_TYPE newType) { mType = newType; }
CFG_MEM_TYPE getMemType() const { return mType; }
bool isMemGlobal() const
{
if (mType == CFG_MEM_TYPE::COMMON_ ||
mType == CFG_MEM_TYPE::MODULE_ ||
mType == CFG_MEM_TYPE::SAVE_)
return true;
return false;
}
bool isParameter() const
{
if (mType == CFG_MEM_TYPE::FUNC_RES_ ||
mType == CFG_MEM_TYPE::FUNC_PARAM_)
return true;
return false;
}
void setValue(const std::string& newValue) { value = newValue; }
const std::string getValue() const
{
if (type == CFG_ARG_TYPE::CONST_STR || type == CFG_ARG_TYPE::CONSTR_REF)
return "'" + value + "'";
else
return value;
}
int getNumber() const { return number; }
std::string getMemTypeStr() const
{
if (mType == CFG_MEM_TYPE::NONE_)
return "none";
else if (mType == CFG_MEM_TYPE::COMMON_)
return "common";
else if (mType == CFG_MEM_TYPE::LOCAL_)
return "local";
else if (mType == CFG_MEM_TYPE::MODULE_)
return "module";
else if (mType == CFG_MEM_TYPE::FUNC_RES_)
return "func_res";
else if (mType == CFG_MEM_TYPE::FUNC_PARAM_)
return "func_par";
else if (mType == CFG_MEM_TYPE::SAVE_)
return "save";
else if (mType == CFG_MEM_TYPE::FILED_)
return "filed";
else
return "error";
}
~Argument() { }
};
class Instruction
{
static int lastNumInstr;
private:
int number;
CFG_OP operation;
Argument* arg1;
Argument* arg2;
Argument* result;
SgStatement* st = NULL;
SgExpression* ex = NULL;
std::string getArgValue(Argument* arg) const
{
if (arg == NULL)
return "";
return arg->getValue();
}
public:
Instruction() : number(lastNumInstr++), operation(CFG_OP::NONE), arg1(NULL), arg2(NULL), result(NULL) { }
Instruction(CFG_OP op, Argument* arg1 = NULL, Argument* arg2 = NULL, Argument* res = NULL, SgStatement* st = NULL, SgExpression* ex = NULL) :
number(lastNumInstr++), operation(op), arg1(arg1), arg2(arg2), result(res), st(st), ex(ex) { }
Instruction(CFG_OP op, SgStatement* st) : number(lastNumInstr++), operation(op), arg1(NULL), arg2(NULL), result(NULL), st(st) { }
Instruction(CFG_OP op, int num, Argument* arg1 = NULL, Argument* arg2 = NULL, Argument* res = NULL, SgStatement* st = NULL, SgExpression* ex = NULL) :
number(num), operation(op), arg1(arg1), arg2(arg2), result(res), st(st), ex(ex) { }
void setOperation(CFG_OP op) { operation = op; }
CFG_OP getOperation() const { return operation; }
Argument* getArg1() const { return arg1; }
Argument* getArg2() const { return arg2; }
Argument* getResult() const { return result; }
void setArg1(Argument* arg) { arg1 = arg; }
void setArg2(Argument* arg) { arg2 = arg; }
void setResult(Argument* arg) { result = arg; }
int getNumber() const { return number; }
void shiftNumber(int add) { number += add; }
SgStatement* getOperator() const { return st; }
void setOperator(SgStatement* st_) { st = st_; }
SgExpression* getExpression() const { return ex; }
int getLine() const { return st ? st->lineNumber() : -1; }
bool isAccess() const
{
std::set<CFG_OP> accessOps = { CFG_OP::LOAD , CFG_OP::STORE, CFG_OP::REC_REF_LOAD, CFG_OP::REC_REF_STORE };
return accessOps.find(operation) != accessOps.end();
}
bool isArith() const
{
std::set<CFG_OP> arithOps = { CFG_OP::ADD, CFG_OP::MULT, CFG_OP::DIV, CFG_OP::SUBT, CFG_OP::UN_ADD, CFG_OP::UN_MINUS, CFG_OP::POW, CFG_OP::CONCAT };
//CFG_OP::CAST, CFG_OP::GE, CFG_OP::LE, CFG_OP::GT, CFG_OP::LT, CFG_OP::EQ, CFG_OP::NEQV, CFG_OP::EQV, CFG_OP::OR, CFG_OP::AND, CFG_OP::NOT };
return (arithOps.find(operation) != arithOps.end()) || isIntirinsicCall();
}
bool isIntirinsicCall() const
{
if (operation == CFG_OP::F_CALL)
{
if (ex)
{
if (isIntrinsicFunctionName(ex->symbol()->identifier()))
return true;
}
}
return false;
}
static int getNextInstrNum() { return lastNumInstr; }
static void shiftNextInstrNum(int byNum) { lastNumInstr += byNum; }
std::string dump()
{
std::string res = "";
std::string resultVal = getArgValue(result);
std::string arg1Val = getArgValue(arg1);
std::string arg2Val = getArgValue(arg2);
switch (operation)
{
case CFG_OP::ADD:
case CFG_OP::MULT:
case CFG_OP::DIV:
case CFG_OP::SUBT:
case CFG_OP::GE:
case CFG_OP::LE:
case CFG_OP::GT:
case CFG_OP::LT:
case CFG_OP::EQ:
case CFG_OP::NEQV:
case CFG_OP::EQV:
case CFG_OP::OR:
case CFG_OP::AND:
case CFG_OP::POW:
case CFG_OP::CONCAT:
res = resultVal + " = " + arg1Val + CFG_OP_S[(int)operation] + arg2Val;
break;
case CFG_OP::NOT:
case CFG_OP::UN_MINUS:
case CFG_OP::UN_ADD:
res = resultVal + " = " + CFG_OP_S[(int)operation] + arg1Val;
break;
case CFG_OP::POINTER_ASS:
res = arg1Val + CFG_OP_S[(int)operation] + resultVal;
break;
case CFG_OP::ASSIGN:
if (arg2)
res = resultVal + CFG_OP_S[(int)operation] + arg1Val + " [" + arg2Val + "]";
else
res = resultVal + CFG_OP_S[(int)operation] + arg1Val;
break;
case CFG_OP::JUMP:
case CFG_OP::ENTRY:
res = CFG_OP_S[(int)operation] + arg1Val;
break;
case CFG_OP::JUMP_IF:
res = CFG_OP_S[(int)operation] + arg1Val + " then goto " + arg2Val;
break;
case CFG_OP::EMPTY:
res = CFG_OP_S[(int)operation];
break;
case CFG_OP::LOAD:
case CFG_OP::REC_REF_LOAD:
res = CFG_OP_S[(int)operation] + resultVal + " " + arg1Val + (arg2 ? (" " + arg2Val) : "");
break;
case CFG_OP::REC_REF_STORE:
case CFG_OP::STORE:
res = CFG_OP_S[(int)operation] + arg1Val + (arg2 ? (" " + arg2Val) : "") + " " + resultVal;
break;
case CFG_OP::REC_REF:
res = "LOAD " + resultVal + " " + arg1Val + CFG_OP_S[(int)operation] + arg2Val;
break;
case CFG_OP::REF:
case CFG_OP::PARAM:
case CFG_OP::IO_PARAM:
res = CFG_OP_S[(int)operation] + arg1Val;
break;
case CFG_OP::CAST:
res = resultVal + " = " + CFG_OP_S[(int)operation] + arg1Val;
break;
case CFG_OP::F_CALL:
if (result)
res = resultVal + " = " + CFG_OP_S[(int)operation] + arg1Val + " " + arg2Val;
else
res = CFG_OP_S[(int)operation] + arg1Val + " " + arg2Val;
break;
case CFG_OP::RANGE:
res = CFG_OP_S[(int)operation] + "[ ";
if (arg1)
res += arg1Val;
res += " : ";
if (arg2)
res += arg2Val;
res += " : ";
if (result)
res += resultVal;
res += " ]";
break;
case CFG_OP::DVM_DIR:
case CFG_OP::SPF_DIR:
res = (st != NULL) ? std::string(st->unparse()) : "NULL";
break;
default:
res = CFG_OP_S[(int)operation];
break;
}
return res;
}
};
class IR_Block
{
private:
Instruction* current;
Instruction* jumpTo;
BasicBlock* bblock;
bool header;
public:
IR_Block(Instruction* instr) : current(instr), jumpTo(NULL), bblock(NULL), header(false) { }
IR_Block(const IR_Block& copyFrom)
{
current = new Instruction(*copyFrom.getInstruction());
bblock = NULL;
//need to replace with actual IR
jumpTo = copyFrom.getJump();
header = false;
}
Instruction* getInstruction() const { return current; }
Instruction* getJump() const { return jumpTo; }
BasicBlock* getBasicBlock() const { return bblock; }
int getNumber() const { return current->getNumber(); }
void setJump(Instruction* instr) { jumpTo = instr; }
void setBasicBlock(BasicBlock* newBlock) { bblock = newBlock; }
void setHeader() { header = true; }
bool isHeader() const { return header; }
int getLine() const { return current->getLine(); }
~IR_Block() { delete current; }
};
class BasicBlock;
}
std::string createName(const std::vector<std::pair<const Variable*, CommonBlock*>>& commonVars, const FuncInfo* func,
SgSymbol* s, SgStatement* scope, SAPFOR::CFG_MEM_TYPE& mType);
std::string getNameByArg(SAPFOR::Argument* arg);
SgSymbol* getSybolByArg(SAPFOR::Argument* arg);
SAPFOR::Argument* createArg(const std::string& fullName, const std::string& name, SAPFOR::CFG_MEM_TYPE mType);
std::vector<SAPFOR::IR_Block*> buildIR(SgStatement* function, const FuncInfo* func, const std::vector<std::pair<const Variable*, CommonBlock*>>& commonVars, const SAPFOR::CFG_Settings settings);
SAPFOR::Instruction* getInstructionByNumber(const std::vector<SAPFOR::IR_Block*>& blocks, int num);
std::pair<SAPFOR::Instruction*, SAPFOR::BasicBlock*> getInstructionAndBlockByNumber(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph, int num);
std::pair<SAPFOR::Instruction*, SAPFOR::BasicBlock*> getInstructionAndBlockByStatement(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph, SgStatement* stmt);
int getParamIndex(SAPFOR::Argument* func_param, int max_index);
void testIR(std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> fullIR);

View File

@@ -0,0 +1,588 @@
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <set>
#include "../Utils/SgUtils.h"
#include "../Utils/CommonBlock.h"
#include "../GraphCall/graph_calls.h"
#include "../ExpressionTransform/expr_transform.h"
#include "dvm.h"
#include "IR.h"
#include "CFGraph.h"
using namespace std;
using namespace SAPFOR;
typedef SAPFOR::BasicBlock BBlock;
typedef SAPFOR::Argument BArgument;
static void printBlock(BBlock* block) {
cout << "block - " << block->getNumber() << endl;
cout << "next -";
for (auto i : block->getNext())
{
cout << " " << i->getNumber();
}
cout << endl << "prev -";
for (auto i : block->getPrev())
{
cout << " " << i->getNumber();
}
cout << endl;
for (auto i : block->getInstructions())
{
string resValue = "";
string arg1Value = "";
string arg2Value = "";
if (i->getInstruction()->getResult() != nullptr && i->getInstruction()->getResult()->getType() == CFG_ARG_TYPE::VAR) {
resValue = i->getInstruction()->getResult()->getValue();
i->getInstruction()->getResult()->setValue(i->getInstruction()->getResult()->getValue() + to_string(i->getInstruction()->getResult()->getNumber()));
}
if (i->getInstruction()->getArg1() != nullptr && i->getInstruction()->getArg1()->getType() == CFG_ARG_TYPE::VAR) {
arg1Value = i->getInstruction()->getArg1()->getValue();
i->getInstruction()->getArg1()->setValue(i->getInstruction()->getArg1()->getValue() + to_string(i->getInstruction()->getArg1()->getNumber()));
}
if (i->getInstruction()->getArg2() != nullptr && i->getInstruction()->getArg2()->getType() == CFG_ARG_TYPE::VAR) {
arg2Value = i->getInstruction()->getArg2()->getValue();
i->getInstruction()->getArg2()->setValue(i->getInstruction()->getArg2()->getValue() + to_string(i->getInstruction()->getArg2()->getNumber()));
}
cout << i->getNumber() << " " << i->getInstruction()->dump() << endl;// << (i->getInstruction()->getResult() != nullptr ? " 1 " : " 0 ") << (i->getInstruction()->getArg1() != nullptr ? "1 " : "0 ") << (i->getInstruction()->getArg2() != nullptr ? "1 " : "0 ") << endl;
/*if (i->getInstruction()->getResult() != nullptr) {
cout << "num - " << i->getInstruction()->getResult()->getNumber() << endl;
})*/
/*if (i->getInstruction()->getOperation() == CFG_OP::F_CALL) {
cout << endl;
cout << "arg1 - " << (i->getInstruction()->getArg1()->getType() == CFG_ARG_TYPE::FUNC ? "1" : "0") << "arg2 - " << (i->getInstruction()->getArg2()->getType() == CFG_ARG_TYPE::CONST ? "1" : "0") << "res - " << i->getInstruction()->getResult() << endl;
}*/
if (i->getInstruction()->getResult() != nullptr && i->getInstruction()->getResult()->getType() == CFG_ARG_TYPE::VAR) {
i->getInstruction()->getResult()->setValue(resValue);
}
if (i->getInstruction()->getArg1() != nullptr && i->getInstruction()->getArg1()->getType() == CFG_ARG_TYPE::VAR) {
i->getInstruction()->getArg1()->setValue(arg1Value);
}
if (i->getInstruction()->getArg2() != nullptr && i->getInstruction()->getArg2()->getType() == CFG_ARG_TYPE::VAR) {
i->getInstruction()->getArg2()->setValue(arg2Value);
}
}
cout << endl;
}
template <typename T>
static bool compareVectors(const vector<T>* vec1, const vector<T>* vec2) {
if (vec1 == vec2) {
return true;
}
if (!vec1 || !vec2) {
return false;
}
vector<T> sortedVec1 = *vec1;
vector<T> sortedVec2 = *vec2;
sort(sortedVec1.begin(), sortedVec1.end());
sort(sortedVec2.begin(), sortedVec2.end());
return sortedVec1 == sortedVec2;
}
template <typename T>
static vector<T>* getCommonElements(const vector<vector<T>>* vectors) {
if (!vectors || vectors->empty()) {
return new vector<T>(); // Return an empty vector if input is null or empty
}
// Start with the first vector
vector<T>* commonElements = new vector<T>((*vectors)[0]);
for (size_t i = 1; i < vectors->size(); ++i) {
vector<T> tempCommon;
// Sort the current vector and common result for intersection
vector<T> sortedVec = (*vectors)[i];
sort(commonElements->begin(), commonElements->end());
sort(sortedVec.begin(), sortedVec.end());
// Find the intersection
set_intersection(
commonElements->begin(), commonElements->end(),
sortedVec.begin(), sortedVec.end(),
back_inserter(tempCommon)
);
// Update common result
*commonElements = tempCommon;
// If no common elements left, break early
if (commonElements->empty()) {
break;
}
}
return commonElements;
}
static map<BBlock*, vector<BBlock*>> findDominators(vector<BBlock*> blocks) {
map<BBlock*, vector<BBlock*>> result;
bool changed = true;
while (changed) {
changed = false;
for (auto currentBlock : blocks) {
auto pred = currentBlock->getPrev();
auto prevDominators = new vector<vector<BBlock*>>();
for (auto predBlock : pred)
prevDominators->push_back(result.find(predBlock) != result.end() ? result[predBlock] : blocks);
auto currentBlockResult = getCommonElements(prevDominators);
currentBlockResult->push_back(currentBlock);
if (result.find(currentBlock) == result.end() || !compareVectors(currentBlockResult, &result[currentBlock])) {
result[currentBlock] = *currentBlockResult;
changed = true;
}
}
}
return result;
}
static void RenumberBlocks(BBlock* current, int* n, map<int, int>* res, set<BBlock*>* visited) {
if (visited->find(current) != visited->end()) {
return;
}
visited->insert(current);
vector<BBlock*> nextBlocks = current->getNext();
sort(nextBlocks.begin(), nextBlocks.end(), [](BBlock* a, BBlock* b) {
return a->getInstructions()[0]->getInstruction()->getOperator()->lineNumber() > b->getInstructions()[0]->getInstruction()->getOperator()->lineNumber();
});
for (auto i : nextBlocks) {
RenumberBlocks(i, n, res, visited);
}
(*res)[current->getNumber()] = *n;
*n -= 1;
}
static map<BBlock*, vector<BBlock*>> findDominatorBorders(vector<BBlock*>& blocks, map<BBlock*, BBlock*>& iDominators) {
map<BBlock*, vector<BBlock*>> result;
for (auto block : blocks) {
result[block] = *(new vector<BBlock*>());
}
for (auto block : blocks) {
if (block->getPrev().size() > 1) {
for (auto prev : block->getPrev()) {
auto tmpBlock = prev;
while (tmpBlock != iDominators[block]) {
result[tmpBlock].push_back(block);
tmpBlock = iDominators[tmpBlock];
}
}
}
}
return result;
}
static BBlock* findImmediateDominatorsDfsHelper(BBlock* block, BBlock* currentBlock, BBlock* currentImmediateDominator, vector<BBlock*> &visited, map<BBlock*, vector<BBlock*>>& dominators) {
if (block == currentBlock) {
return currentImmediateDominator;
}
if (find(visited.begin(), visited.end(), currentBlock) != visited.end()) {
return nullptr;
}
visited.push_back(currentBlock);
if (find(dominators[block].begin(), dominators[block].end(), currentBlock) != dominators[block].end()) {
currentImmediateDominator = currentBlock;
}
for (auto nextBlock : currentBlock->getNext()) {
auto result = findImmediateDominatorsDfsHelper(block, nextBlock, currentImmediateDominator, visited, dominators);
if (result) {
return result;
}
}
return nullptr;
}
static map<BBlock*, BBlock*> findImmediateDominators(map<BBlock*, vector<BBlock*>>& dominators, BBlock* fistBlock) {
map<BBlock*, BBlock*> iDominators;
for (const auto& domPair : dominators) {
BBlock* block = domPair.first;
const vector<BBlock*>& domBlocks = domPair.second;
vector<BBlock*> visited;
if (block == fistBlock) {
continue;
}
iDominators[block] = findImmediateDominatorsDfsHelper(block, fistBlock, fistBlock, visited, dominators);
}
return iDominators;
}
static vector<BArgument*> getDefForBlock(const BBlock& block) {
vector<BArgument*> def;
const auto& instructions = block.getInstructions();
for (const auto& irBlock : instructions) {
if (irBlock) {
Instruction* instr = irBlock->getInstruction();
if (instr) {
BArgument* result = instr->getResult();
if (result) {
def.push_back(result);
}
}
}
}
return def;
}
static pair<set<BArgument*>, map<BArgument*, set<BBlock*>>> getGlobalsAndVarBlocks(vector<BBlock*> blocks) {
set<BArgument*> globals;
map<BArgument*, set<BBlock*>> varBlocks;
for (auto block : blocks) {
set<BArgument*> def;
const auto& instructions = block->getInstructions();
for (const auto& irBlock : instructions) {
if (irBlock) {
Instruction* instr = irBlock->getInstruction();
if (instr) {
auto arg1 = instr->getArg1();
auto arg2 = instr->getArg2();
auto res = instr->getResult();
if (arg1 && arg1->getType() == CFG_ARG_TYPE::VAR && find(def.begin(), def.end(), arg1) == def.end()) {
globals.insert(arg1);
}
if (arg2 && arg2->getType() == CFG_ARG_TYPE::VAR && find(def.begin(), def.end(), arg2) == def.end()) {
globals.insert(arg2);
}
if (res && res->getType() == CFG_ARG_TYPE::VAR) {
def.insert(res);
varBlocks[res].insert(block);
}
}
}
}
}
return make_pair(globals, varBlocks);
}
static vector<BBlock*> getBlocksWithFiFunctions(vector<BBlock*> blocks, set<BArgument*> globals, map<BArgument*, set<BBlock*>> varBlocks, map<BBlock*, vector<BBlock*>> dominatorBorders) {
vector<BBlock*> blocksWithFiFunctions;
auto fiFunc = new BArgument(CFG_ARG_TYPE::FUNC, CFG_MEM_TYPE::NONE_, "FI_FUNCTION");
auto paramCount = new BArgument(CFG_ARG_TYPE::CONST, CFG_MEM_TYPE::LOCAL_, "0");
for (auto var : globals) {
auto worklist = varBlocks[var];
set<BBlock*> hasFiFunction;
while (!worklist.empty()) {
auto block = *worklist.begin();
worklist.erase(block);
for (auto dfBlock : dominatorBorders[block]) {
if (hasFiFunction.find(dfBlock) == hasFiFunction.end()) {
hasFiFunction.insert(dfBlock);
Instruction* phiInstruction = new Instruction(CFG_OP::F_CALL, fiFunc, paramCount, var);
//cout << "insert fi functio9n in " << dfBlock->getNumber() << " with var " << var->getValue() << endl;
IR_Block* phiBlock = new IR_Block(phiInstruction);
dfBlock->addInstructionInFront(phiBlock);
blocksWithFiFunctions.push_back(dfBlock);
}
}
}
}
return blocksWithFiFunctions;
}
string ToString(CFG_ARG_TYPE type) {
switch (type) {
case CFG_ARG_TYPE::NONE: return "NONE";
case CFG_ARG_TYPE::REG: return "REG";
case CFG_ARG_TYPE::VAR: return "VAR";
case CFG_ARG_TYPE::ARRAY: return "ARRAY";
case CFG_ARG_TYPE::CONST: return "CONST";
case CFG_ARG_TYPE::FUNC: return "FUNC";
case CFG_ARG_TYPE::LAB: return "LAB";
case CFG_ARG_TYPE::INSTR: return "INSTR";
case CFG_ARG_TYPE::CONST_STR: return "CONST_STR";
case CFG_ARG_TYPE::RECORD: return "RECORD";
case CFG_ARG_TYPE::CONSTR_REF: return "CONSTR_REF";
default: return "UNKNOWN";
}
}
void restoreConnections(const vector<BBlock*>& originalBlocks, vector<BBlock*>& copiedBlocks) {
// Создаем отображение оригинальных блоков в их копии
map<BBlock*, BBlock*> blockMapping;
for (size_t i = 0; i < originalBlocks.size(); ++i) {
blockMapping[originalBlocks[i]] = copiedBlocks[i];
}
// Восстанавливаем связи между копиями
for (size_t i = 0; i < originalBlocks.size(); ++i) {
BBlock* originalBlock = originalBlocks[i];
BBlock* copiedBlock = copiedBlocks[i];
for (auto j : copiedBlock->getPrev()) {
copiedBlock->removePrev(j);
}
for (auto j : copiedBlock->getNext()) {
copiedBlock->removeNext(j);
}
// Восстанавливаем связи succ (следующих блоков)
for (auto* succ : originalBlock->getNext()) {
copiedBlock->addNext(blockMapping[succ]);
}
// Восстанавливаем связи prev (предыдущих блоков)
for (auto* prev : originalBlock->getPrev()) {
copiedBlock->addPrev(blockMapping[prev]);
}
}
}
BArgument* NewName(BArgument* var, map<string, int>& counter, map<string, stack<BArgument*>>& stack) {
int index = counter[var->getValue()];
counter[var->getValue()]++;
BArgument* newName = new BArgument(var->getType(), var->getMemType(), var->getValue(), index + 1);
stack[var->getValue()].push(newName);
return newName;
}
void RenameFiFunctionResultVar(BBlock* block, map<string, int>& counter, map<string, stack<BArgument*>>& stack) {
for (auto irBlock : block->getInstructions()) {
auto instruction = irBlock->getInstruction();
if (instruction->getOperation() == CFG_OP::F_CALL && instruction->getArg1() != nullptr && instruction->getArg1()->getValue() == "FI_FUNCTION" && instruction->getResult() != nullptr) {
instruction->setResult(NewName(instruction->getResult(), counter, stack));
}
}
}
void RenameInstructionVars(BBlock* block, map<string, int>& counter, map<string, stack<BArgument*>>& stack) {
for (auto irBlock : block->getInstructions()) {
auto instruction = irBlock->getInstruction();
if (instruction->getArg1() != nullptr && instruction->getArg1()->getType() == CFG_ARG_TYPE::VAR) {
instruction->setArg1(stack[instruction->getArg1()->getValue()].top());
}
if (instruction->getArg2() != nullptr && instruction->getArg2()->getType() == CFG_ARG_TYPE::VAR) {
instruction->setArg2(stack[instruction->getArg2()->getValue()].top());
}
if (instruction->getResult() != nullptr && instruction->getResult()->getType() == CFG_ARG_TYPE::VAR) {
instruction->setResult(NewName(instruction->getResult(), counter, stack));
}
}
}
void RenameFiFunctionArgsVar(BBlock* block, map<string, stack<BArgument*>>& stack) {
cout << "test" << endl;
auto size = block->getInstructions().size();
for (auto i = 0; i < size; i++) {
auto irBlock = block->getInstructions()[i];
auto instruction = irBlock->getInstruction();
if (instruction->getOperation() == CFG_OP::F_CALL && instruction->getArg1() != nullptr && instruction->getArg1()->getValue() == "FI_FUNCTION" && instruction->getResult() != nullptr) {
//cout << "test" << endl;
auto paramInstruction = new Instruction(CFG_OP::PARAM, stack[instruction->getResult()->getValue()].top());
block->addInstructionBeforeInstruction(new IR_Block(paramInstruction), instruction);
i++;
}
}
}
vector<BBlock*> findBlocksWithValue(map<BBlock*, BBlock*>& iDominators, BBlock* x) {
vector<BBlock*> result;
// Проходим по всем элементам map
for (auto& pair : iDominators) {
// Если значение равно x, добавляем ключ в результат
if (pair.second == x) {
result.push_back(pair.first);
}
}
return result;
}
void RenameIR(BBlock* block, map<BBlock*, BBlock*>& iDominators, map<string, int>& counter, map<string, stack<BArgument*>>& stack) {
RenameFiFunctionResultVar(block, counter, stack);
RenameInstructionVars(block, counter, stack);
for (auto* successor : block->getNext()) {
RenameFiFunctionArgsVar(successor, stack);
}
for (auto* child : findBlocksWithValue(iDominators, block)) {
cout << "sec" << endl;
RenameIR(child, iDominators, counter, stack);
}
for (auto& irBlock : block->getInstructions()) {
auto instruction = irBlock->getInstruction();
if (instruction->getResult() != nullptr && instruction->getResult()->getType() == CFG_ARG_TYPE::VAR) {
string varName = instruction->getResult()->getValue();
stack[varName].pop();
}
}
for (auto& irBlock : block->getInstructions()) {
auto instruction = irBlock->getInstruction();
if (instruction->getOperation() == CFG_OP::F_CALL && instruction->getArg1() != nullptr && instruction->getArg1()->getValue() == "FI_FUNCTION" && instruction->getResult() != nullptr) {
string varName = instruction->getResult()->getValue();
stack[varName].pop();
}
}
}
map<FuncInfo*, vector<BBlock*>> buildIRSSAForm(map<FuncInfo*, vector<BBlock*>> fullIR) {
map<FuncInfo*, vector<BBlock*>> result;
for (auto item : fullIR) {
auto funcinfo = item.first;
auto funcIRConst = item.second;
vector<BBlock*> funcIR;
vector<BBlock*> funcResult;
for (auto i : funcIRConst) {
funcIR.push_back(new BBlock(*i));
}
restoreConnections(funcIRConst, funcIR);
for (auto i : funcIR) {
//printBlock(i);
}
auto dominators = findDominators(funcIR);
/*cout << endl << endl << endl << "DOMINATORS" << endl << endl << endl;
for (auto i : dominators) {
cout << "block - " << i.first->getNumber() << endl;
for (auto j : i.second) {
cout << "dominators - " << j->getNumber() << endl;
}
cout << endl;
}*/
auto iDominators = findImmediateDominators(dominators, funcIR[0]);
/*for (auto i : iDominators) {
cout << "block - " << i.first->getNumber() << endl;
cout << "Idominators - " << i.second->getNumber() << endl;
cout << endl;
}
*/
auto dominatorBorders = findDominatorBorders(funcIR, iDominators);
/*for (auto i : dominatorBorders) {
cout << "block - " << i.first->getNumber() << endl;
for (auto j : i.second) {
cout << "border - " << j->getNumber() << endl;
}
cout << endl;
}*/
auto globalsAndVarBlocks = getGlobalsAndVarBlocks(funcIR);
auto globals = globalsAndVarBlocks.first;
auto varBlocks = globalsAndVarBlocks.second;
/*for (auto i : globals) {
cout << i->getValue() << " " << ToString(i->getType()) << " " << i->getNumber() << endl;
}
cout << endl;
for (auto i : varBlocks) {
cout << i.first->getValue() << " - ";
for (auto j : i.second) {
cout << j->getNumber() << ", ";
}
cout << endl;
}
cout << endl;
*/
funcResult = getBlocksWithFiFunctions(funcIR, globals, varBlocks, dominatorBorders);
map<string, int> count;
map<string, stack<BArgument*>> varStack;
for (auto var : globals) {
count[var->getValue()] = 0;
stack<BArgument*> tmp;
varStack[var->getValue()] = tmp;
}
RenameIR(funcIR[0], iDominators, count, varStack);
for (auto i : funcIR) {
printBlock(i);
}
cout << endl << endl << endl << endl << endl;
for (auto i : funcIRConst) {
printBlock(i);
}
result[funcinfo] = funcResult;
}
return result;
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include "CFGraph.h"
#include "IR.h"
std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> buildIRSSAForm(std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> fullIR);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
#pragma once
#include<unordered_map>
#include "../Utils/SgUtils.h"
#include "../Utils/CommonBlock.h"
#include "../GraphCall/graph_calls.h"
#include "CFGraph.h"
#include "IR.h"
inline bool hasStoreStructure(SAPFOR::CFG_OP type)
{
return (type == SAPFOR::CFG_OP::STORE) ||
(type == SAPFOR::CFG_OP::REC_REF_STORE) ||
(type == SAPFOR::CFG_OP::POINTER_ASS);
}
const std::map<std::string, SgSymbol*>& getCommonArgsByFunc(FuncInfo* func, std::map<FuncInfo*, std::map<std::string, SgSymbol*>>& cache,
const std::vector<std::pair<const Variable*, CommonBlock*>>& commonVars,
std::unordered_map<SgSymbol*, std::string>& globals_cache,
std::unordered_map<SgSymbol*, std::string>& locals_cache);
std::vector<SAPFOR::BasicBlock*> sortCfgNodes(const std::vector<SAPFOR::BasicBlock*>& blocks,
std::set<std::pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>>* ignored_edges = NULL);
const std::string& getArgNameBySymbol(const std::vector<std::pair<const Variable*, CommonBlock*>>& commonVars,
const FuncInfo* func, SgSymbol* s, std::unordered_map<SgSymbol*, std::string>& globals_cache,
std::unordered_map<SgSymbol*, std::string>& locals_cache);
// main functions of SUBST_EXPR_RD pass
void buildSubstitutions(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project, const std::map<std::string, CommonBlock*>& commonBlocks, SgProject* project);
void performRDSubst(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project, const std::map<std::string, CommonBlock*>& commonBlocks, SgProject* project);
void revertSubstitutions();
void cancelRevertionForStatement(std::string filename, SgStatement* stmt, int i);
/*void destroyReplacementsInFiles();
void destroyOldExpressionsInFile();
void destroyAllSubstitutionsData();*/

View File

@@ -0,0 +1,761 @@
#include "live_variable_analysis.h"
#include "RD_subst.h"
#include "DataFlow/backward_data_flow.h"
#include <string>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <unordered_map>
#include <algorithm>
using std::string;
using std::pair;
using std::vector;
using std::map;
using std::set;
using std::unordered_map;
using std::list;
using LIVE_VARIABLES::LiveDeadVarsForCall;
namespace SAPFOR
{
bool BasicBlock::addLive(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& to_add, bool in) {
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& current_set = (in ? live_in : live_out);
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& opposite_set = (!in ? live_in : live_out);
bool inserted = false;
for (const auto& byNew : to_add)
{
const vector<SAPFOR::BasicBlock*>& add_in_live = byNew.second;
vector<SAPFOR::BasicBlock*> new_in_live = {};
auto current_set_iter = current_set.find(byNew.first);
if (current_set_iter == current_set.end())
new_in_live = add_in_live;
else
std::set_difference(add_in_live.begin(), add_in_live.end(), current_set_iter->second.begin(), current_set_iter->second.end(), std::inserter(new_in_live, new_in_live.begin()));
auto opposite_set_iter = opposite_set.find(byNew.first);
auto both_set_iter = live_inout.find(byNew.first);
if (new_in_live.size() != 0)
{
inserted = true;
bool current_set_has_argument = current_set_iter != current_set.end();
bool opposite_set_has_argument = opposite_set_iter != opposite_set.end();
bool both_set_has_argument = both_set_iter != live_inout.end();
for (SAPFOR::BasicBlock* bb : new_in_live)
{
bool insert_to_both = false;
if (opposite_set_has_argument)
{
auto& usages_from_opposite = opposite_set_iter->second;
auto find_bb_from_opposite = std::lower_bound(usages_from_opposite.begin(), usages_from_opposite.end(), bb);
if (find_bb_from_opposite != usages_from_opposite.end() && *find_bb_from_opposite == bb)
{
insert_to_both = true;
usages_from_opposite.erase(find_bb_from_opposite);
if (usages_from_opposite.size() == 0) {
opposite_set.erase(opposite_set_iter);
opposite_set_has_argument = false;
}
}
}
if (insert_to_both)
{
if (!both_set_has_argument) {
both_set_iter = live_inout.insert({ byNew.first, {} }).first;
both_set_has_argument = true;
}
}
else
{
if (!current_set_has_argument) {
current_set_iter = current_set.insert({ byNew.first, {} }).first;
current_set_has_argument = true;
}
}
vector<SAPFOR::BasicBlock*>& dest = insert_to_both ? both_set_iter->second : current_set_iter->second;
auto find_bb_from_dest = std::lower_bound(dest.begin(), dest.end(), bb);
if (find_bb_from_dest == dest.end() || *find_bb_from_dest != bb)
dest.insert(find_bb_from_dest, bb);
}
}
}
return inserted;
}
bool BasicBlock::removeLive(SAPFOR::Argument* to_remove, bool in)
{
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& current_set = (in ? live_in : live_out);
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& opposite_set = (!in ? live_in : live_out);
bool removed = false;
removed |= (current_set.erase(to_remove) != 0);
auto it = live_inout.find(to_remove);
if (it != live_inout.end())
{
auto& dest = opposite_set[to_remove];
for (SAPFOR::BasicBlock* bb : it->second)
{
auto find_bb_from_dest = std::lower_bound(dest.begin(), dest.end(), bb);
if (find_bb_from_dest == dest.end() || *find_bb_from_dest != bb)
dest.insert(find_bb_from_dest, bb);
}
live_inout.erase(to_remove);
removed = true;
}
return removed;
}
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> BasicBlock::getLive(bool in) const {
auto& current_set = in ? live_in : live_out;
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> res;
for (auto& by_source : { current_set, live_inout })
{
for (auto& by_pair : by_source)
{
auto& dest = res[by_pair.first];
auto dest_copy = dest;
dest.resize(dest_copy.size() + by_pair.second.size());
set_union(dest_copy.begin(), dest_copy.end(), by_pair.second.begin(), by_pair.second.end(), dest.begin());
}
}
return res;
}
void BasicBlock::compressLives() {
for (auto& bySrc : { &live_in, &live_out, &live_inout })
for (auto& byArg : *bySrc)
byArg.second.shrink_to_fit();
}
}
bool LiveDeadVarsForCall::tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
{
if (b == block || dest.find(block) == dest.end())
{
dest.insert(b);
return true;
}
return false;
}
LiveDeadVarsForCall::LiveDeadVarsForCall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
{
block = b;
func = f;
int param_size = p.size();
params = vector<SAPFOR::Argument*>(param_size, NULL);
for (int i = 0; i < param_size; i++)
if (f->funcParams.isArgOut(i))
params[i] = p[i];
}
void LiveDeadVarsForCall::make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b)
{
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
{
if (commons_dead_after.find(arg) == commons_dead_after.end())
tryInsert(commons_live_after[arg], b);
}
auto it = find(params.begin(), params.end(), arg);
if (it != params.end())
{
int idx = it - params.begin();
if (dead_after.find(idx) == dead_after.end())
tryInsert(live_after[idx], b);
}
}
void LiveDeadVarsForCall::make_dead(SAPFOR::Argument* arg)
{
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
{
if (commons_live_after.find(arg) == commons_live_after.end())
commons_dead_after.insert(arg);
}
auto it = find(params.begin(), params.end(), arg);
if (it != params.end())
{
int idx = it - params.begin();
if (live_after.find(idx) == live_after.end())
dead_after.insert(idx);
}
}
void LiveDeadVarsForCall::updateFromOut()
{
for (const auto& p : block->getLiveOut())
for (auto b : p.second)
make_live(p.first, b);
}
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead);
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
const map<string, FuncInfo*>& funcByName, bool interprocedural);
class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>> {
private:
set<SAPFOR::Argument*> live, dead;
public:
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getIn()
{
return getBlock()->getLiveOut();
}
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getOut()
{
return getBlock()->getLiveIn();
}
bool addIn(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
{
return getBlock()->addLiveOut(data);
}
bool addOut(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
{
return getBlock()->addLiveIn(data);
}
DATA_FLOW_UPD_STATUS forwardData(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
{
bool inserted = false;
for (const auto& byArg : data)
if (live.find(byArg.first) == live.end() && dead.find(byArg.first) == dead.end())
inserted |= getBlock()->addLiveIn({ byArg });
return inserted ? DATA_FLOW_UPD_STATUS::PROPAGATED : DATA_FLOW_UPD_STATUS::NO_CHANGE;
}
LiveVarAnalysisNode(SAPFOR::BasicBlock* block, vector<SAPFOR::Argument*>& formal_parameters,
vector<LiveDeadVarsForCall>& fcalls, const map<string, FuncInfo*>& funcByName)
{
setBlock(block);
buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName, true);
for (SAPFOR::Argument* arg : live)
getBlock()->addLiveIn({ { arg, { getBlock() } } });
}
};
class LiveVarAnalysis : public BackwardDataFlowAnalysis<LiveVarAnalysisNode> {
protected:
vector<SAPFOR::Argument*>& formal_parameters;
vector<LiveDeadVarsForCall>& fcalls;
const map<string, FuncInfo*>& funcByName;
LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override {
return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName);
}
public:
LiveVarAnalysis(vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
const map<string, FuncInfo*>& funcByName) : formal_parameters(formal_parameters), fcalls(fcalls), funcByName(funcByName)
{ }
};
void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
vector<SAPFOR::Argument*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
bool& last_stack_op,
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
{
for (auto arg : { instr->getArg1(), instr->getArg2(), instr->getResult() })
if (arg && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_)
formal_parameters[getParamIndex(arg, formal_parameters.size())] = arg;
last_stack_op = false;
SAPFOR::Argument* res_arg = NULL;
static const set<SAPFOR::CFG_OP> skip = { SAPFOR::CFG_OP::ENTRY };
SAPFOR::CFG_OP instr_operation = instr->getOperation();
if (instr_operation == SAPFOR::CFG_OP::F_CALL ||
instr_operation == SAPFOR::CFG_OP::STORE ||
instr_operation == SAPFOR::CFG_OP::LOAD)
{
res_arg = (instr_operation == SAPFOR::CFG_OP::STORE ? instr->getArg1() : instr->getResult());
if(instr_operation != SAPFOR::CFG_OP::F_CALL)
use.insert(instr_operation != SAPFOR::CFG_OP::STORE ? instr->getArg1() : instr->getResult());
arg_stack_size = stoi(instr->getArg2()->getValue());
arg_stack.clear();
arg_stack.resize(arg_stack_size);
arg_stack_index = arg_stack_size - 1;
if(instr_operation == SAPFOR::CFG_OP::F_CALL)
fName = instr->getArg1()->getValue();
}
else if (hasStoreStructure(instr_operation))
{
res_arg = instr->getArg1();
set<SAPFOR::Argument*> instr_args = { instr->getResult(), instr->getArg2() };
use.insert(instr_args.begin(), instr_args.end());
}
else if (instr_operation == SAPFOR::CFG_OP::PARAM || instr_operation == SAPFOR::CFG_OP::REF)
{
arg_stack[arg_stack_index--] = instr->getArg1();
}
else if (skip.find(instr_operation) == skip.end())
{
//default
res_arg = instr->getResult();
std::set<SAPFOR::Argument*> intr_args = { instr->getArg1(), instr->getArg2() };
use.insert(intr_args.begin(), intr_args.end());
}
else
{
//skip
return;
}
if (arg_stack_index < 0) {
if(instr_operation == SAPFOR::CFG_OP::PARAM || instr_operation == SAPFOR::CFG_OP::F_CALL)
{
auto func_it = funcByName.find(fName);
if (interprocedural && func_it != funcByName.end())
{
fcalls.push_back(LiveDeadVarsForCall(func_it->second, block, arg_stack));
auto r_it = fcalls.rbegin();
auto r_end = fcalls.rend();
for (auto e : def)
r_it->make_dead(e);
for (auto e : use)
r_it->make_live(e, block);
}
set<SAPFOR::Argument*> make_live, make_dead;
if (fName == "_READ")
def.insert(arg_stack.begin(), arg_stack.end());
else if (interprocedural && getLiveDead(arg_stack, fName, make_live, make_dead))
{
use.insert(make_live.begin(), make_live.end());
def.insert(make_dead.begin(), make_dead.end());
}
else if (func_it != funcByName.end())
{
int arg_num = arg_stack.size();
for (int i = 0; i < arg_num; i++)
{
if(func_it->second->funcParams.isArgOut(i))
def.insert(arg_stack[i]);
if (func_it->second->funcParams.isArgIn(i))
use.insert(arg_stack[i]);
}
}
else
use.insert(arg_stack.begin(), arg_stack.end());
fName = "";
}
else
{
use.insert(arg_stack.begin(), arg_stack.end());
}
arg_stack_index = 0;
arg_stack_size = 0;
arg_stack.clear();
last_stack_op = true;
}
if (res_arg)
def.insert(res_arg);
}
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
vector<SAPFOR::Argument*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
{
set<SAPFOR::Argument*> res, args;
bool last_stack_op;
getUseDefForInstruction(block, instr,
args, res,
formal_parameters, fcalls,
arg_stack, arg_stack_index, arg_stack_size,
last_stack_op,
fName, funcByName,
interprocedural
);
for (auto e : res)
{
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
{
def.insert(e);
use.erase(e);
}
}
for (auto e : args)
{
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
{
use.insert(e);
def.erase(e);
}
}
}
//Build use and def sets of block. Result are stored in use and def
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
const map<string, FuncInfo*>& funcByName, bool interprocedural)
{
vector<SAPFOR::Argument*> arg_stack;
int arg_stack_index = 0, arg_stack_size = 0;
string fName;
const auto& instructions = block->getInstructions();
auto ir_block_it = instructions.rbegin(), ir_block_end = instructions.rend();
for (; ir_block_it != ir_block_end; ir_block_it++)
{
updateUseDefForInstruction(block, (*ir_block_it)->getInstruction(),
use, def,
formal_parameters, fcalls,
arg_stack, arg_stack_index, arg_stack_size,
fName, funcByName,
interprocedural
);
}
}
// prints info about live variables
void doDumpLive(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project)
{
for (const auto& byFunc : CFGraph_for_project)
{
__spf_print(1, "============================================\n");
__spf_print(1, "Live variables '%s' function\n", byFunc.first->funcName.c_str());
__spf_print(1, "============================================\n");
for (auto byBB : byFunc.second)
{
__spf_print(1, "[BB %d]\n", byBB->getNumber());
__spf_print(1, " IN:\n");
for (const auto& live : byBB->getLiveIn())
{
__spf_print(1, " %s:", live.first->getValue().c_str());
for (auto use : live.second)
__spf_print(1, " %d", use->getNumber());
__spf_print(1, "\n");
}
__spf_print(1, " OUT:\n");
for (const auto& live : byBB->getLiveOut())
{
__spf_print(1, " %s:", live.first->getValue().c_str());
for (auto use : live.second)
__spf_print(1, " %d", use->getNumber());
__spf_print(1, "\n");
}
}
}
}
// sets for the next function
static map<string, pair<set<int>, set<SAPFOR::Argument*>>> live_by_func, dead_by_func;
// fill sets of arguments wich becomes live or dead after call of this function
static void fillLiveDeadArgs(const FuncInfo* func, const vector<SAPFOR::BasicBlock*>& blocks)
{
if (blocks.size() == 0)
return;
SAPFOR::BasicBlock* entrypoint = NULL;
int entrypoint_first_instr = 0;
set<SAPFOR::BasicBlock*> exits = {};
for (auto block : blocks)
{
if (block->getNext().size() == 0)
exits.insert(block);
if (block->getInstructions().front()->isHeader())
{
if (!entrypoint || block->getInstructions()[0]->getNumber() < entrypoint_first_instr)
{
entrypoint_first_instr = block->getInstructions()[0]->getNumber();
entrypoint = block;
}
}
}
if (!entrypoint)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
set<int> live, dead;
set<SAPFOR::Argument*> common_live, common_dead;
for (const auto& arg : entrypoint->getLiveIn())
{
switch (arg.first->getMemType())
{
case SAPFOR::CFG_MEM_TYPE::COMMON_:
case SAPFOR::CFG_MEM_TYPE::MODULE_:
common_live.insert(arg.first);
break;
case SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_:
{
int num = getParamIndex(arg.first, func->funcParams.countOfPars);
if (func->funcParams.isArgIn(num))
live.insert(num);
break;
}
}
}
for (auto byExit : exits)
{
for (const auto& byRd : byExit->getRD_Out())
{
auto out_arg = byRd.first;
if (!(byRd.second.size() == 1 && *(byRd.second.begin()) < 0))
{
switch (out_arg->getMemType())
{
case SAPFOR::CFG_MEM_TYPE::COMMON_:
case SAPFOR::CFG_MEM_TYPE::MODULE_:
if (!common_live.count(out_arg))
common_dead.insert(out_arg);
break;
case SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_:
{
int num = getParamIndex(out_arg, func->funcParams.countOfPars);
if (!live.count(num) && func->funcParams.isArgOut(num))
dead.insert(num);
break;
}
}
}
}
}
live_by_func[func->funcName] = { live, common_live };
dead_by_func[func->funcName] = { dead, common_dead };
}
// unite global arguments and actual parameters with given indexes for function
// stores the result in the last argument
bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params,
const map<string, pair<set<int>, set<SAPFOR::Argument*>>>& params_and_globals,
const string& func_name, set<SAPFOR::Argument*>& result)
{
auto globals_it = params_and_globals.find(func_name);
if (globals_it == params_and_globals.end())
return false;
const auto& param_indexes = globals_it->second.first;
const auto& globals = globals_it->second.second;
int params_size = params.size();
for (int idx : param_indexes)
{
if (idx < params_size) {
if (params[idx] && params[idx]->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
result.insert(params[idx]);
}
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
result.insert(globals.begin(), globals.end());
return true;
}
// fill sets of arguments wich becomes live or dead after call with parameters params
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead)
{
return joinGlobalsWithParameters(params, live_by_func, func_name, live) &&
joinGlobalsWithParameters(params, dead_by_func, func_name, dead);
}
// entrypoint for live variable analysis pass
void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project)
{
/*
Here we assume that there is no recursive (explicit or implicit) calls.
So it is easy to process CALL instruction: just use live_in set of first block
for this function (that has already been built).
*/
map<FuncInfo*, set<FuncInfo*>> callDeps;
map<string, FuncInfo*> funcByName;
for (auto& byFunc : CFGraph_for_project)
{
callDeps[byFunc.first].insert(byFunc.first->callsFromV.begin(), byFunc.first->callsFromV.end());
funcByName[byFunc.first->funcName] = byFunc.first;
}
vector<set<FuncInfo*>> scc;
vector<set<FuncInfo*>> callLvls = groupByCallDependencies(callDeps, scc);
map<string, LiveVarAnalysis*> func_to_analysis_object;
map<string, vector<SAPFOR::Argument*>> func_to_parameters;
list<vector<LiveDeadVarsForCall>> live_for_fcalls;
//TODO: take into account ssc structure
// main stage
for (auto& byLvl : callLvls)
{
live_for_fcalls.push_front({});
auto& curr_fcalls = live_for_fcalls.front();
for (auto& byFunc : byLvl)
{
auto itCFG = CFGraph_for_project.find(byFunc);
if (itCFG == CFGraph_for_project.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto& params = func_to_parameters[byFunc->funcName] = vector<SAPFOR::Argument*>(byFunc->funcParams.countOfPars, NULL);
LiveVarAnalysis* analysis_object = (func_to_analysis_object[byFunc->funcName] = new LiveVarAnalysis(params, curr_fcalls, funcByName));
analysis_object->fit(itCFG->second);
analysis_object->analyze();
fillLiveDeadArgs(byFunc, itCFG->second);
}
}
// interprocedural analysis
for (auto& calls_vector : live_for_fcalls)
{
map<FuncInfo*, LiveDeadVarsForCall> assembled_fcalls;
for (auto& call : calls_vector)
{
call.updateFromOut();
call.params.clear();
call.commons_dead_after.clear();
call.dead_after.clear();
auto it = assembled_fcalls.find(call.func);
if (it == assembled_fcalls.end())
it = assembled_fcalls.insert({ call.func, LiveDeadVarsForCall(call.func, call.block, {}) }).first;
for (const auto& p : call.live_after)
it->second.live_after[p.first].insert(p.second.begin(), p.second.end());
for (const auto& p : call.commons_live_after)
it->second.commons_live_after[p.first].insert(p.second.begin(), p.second.end());
}
for (const auto& func : assembled_fcalls)
{
auto func_it = func_to_analysis_object.find(func.first->funcName);
if (func_it == func_to_analysis_object.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto param_it = func_to_parameters.find(func.first->funcName);
if (param_it == func_to_parameters.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const vector<SAPFOR::Argument*>& params = param_it->second;
auto params_begin = params.begin(), params_end = params.end();
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> live_after = func.second.commons_live_after;
for (auto curr = params_begin; curr < params_end; curr++)
{
if (*curr)
{
const auto& live_param_it = func.second.live_after.find(curr - params_begin);
if (live_param_it != func.second.live_after.end())
live_after[*curr].insert(live_param_it->second.begin(), live_param_it->second.end());
}
}
set<LiveVarAnalysisNode*> exits;
int max_cnt = LiveVarAnalysisNode::getStartCounter();
for (auto block : func_it->second->getNodes())
{
if (block->getBlock()->getNext().size() == 0)
exits.insert(block);
if (block->getInCnt() > max_cnt)
max_cnt = block->getInCnt();
}
max_cnt++;
for (auto exit : exits)
{
for (const auto& byArg : live_after)
{
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> converted;
converted[byArg.first] = vector<SAPFOR::BasicBlock*>(byArg.second.begin(), byArg.second.end());
if (exit->addIn(converted))
{
exit->setInCnt(max_cnt);
if (exit->forwardData(converted) != DATA_FLOW_UPD_STATUS::NO_CHANGE)
exit->setOutCnt(max_cnt);
}
}
}
// now we can update live sets in all blocks
func_it->second->analyze();
}
}
for (const auto& byFunc : func_to_analysis_object)
delete byFunc.second;
for (auto& byFunc : CFGraph_for_project)
for (auto& byBlock : byFunc.second)
byBlock->compressLives();
live_by_func.clear();
dead_by_func.clear();
}

View File

@@ -0,0 +1,55 @@
#pragma once
#include "../Utils/SgUtils.h"
#include "CFGraph.h"
namespace LIVE_VARIABLES
{
/* Store information about live and dead variables after call operator */
/* (needed for interprocedural part of live variable analysis) */
class LiveDeadVarsForCall
{
private:
bool tryInsert(std::set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b);
public:
FuncInfo* func;
std::map<int, std::set<SAPFOR::BasicBlock*>> live_after;
std::set<int> dead_after;
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> commons_live_after;
std::set<SAPFOR::Argument*> commons_dead_after;
std::vector<SAPFOR::Argument*> params;
SAPFOR::BasicBlock* block;
LiveDeadVarsForCall(FuncInfo* f, SAPFOR::BasicBlock* b, const std::vector<SAPFOR::Argument*>& p);
void make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b);
void make_dead(SAPFOR::Argument* arg);
void updateFromOut();
};
}
template <class IT, class DEST>
void insertIfVar(IT begin, IT end, DEST& to) {
for (auto it = begin; it != end; it++)
if (*it && (*it)->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
to.insert(*it);
}
void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
std::set<SAPFOR::Argument*>& use, std::set<SAPFOR::Argument*>& def,
std::vector<SAPFOR::Argument*>& formal_parameters, std::vector<LIVE_VARIABLES::LiveDeadVarsForCall>& fcalls,
std::vector<SAPFOR::Argument*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
bool& last_stack_op,
std::string& fName, const std::map<std::string, FuncInfo*>& funcByName, bool interprocedural);
void runLiveVariableAnalysis(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project);
void doDumpLive(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project);
bool joinGlobalsWithParameters(const std::vector<SAPFOR::Argument*>& params,
const std::map<std::string, std::pair<std::set<int>, std::set<SAPFOR::Argument*>>>& params_and_globals,
const std::string& func_name, std::set<SAPFOR::Argument*>& result);

View File

@@ -0,0 +1,539 @@
#include "../Utils/errors.h"
#include "private_variables_analysis.h"
#include "../GraphLoop/graph_loops.h"
#include "../LoopAnalyzer/loop_analyzer.h"
#include "../SageAnalysisTool/depGraph.h"
#include "../DirectiveProcessing/directive_parser.h"
#include "live_variable_analysis.h"
#include "RD_subst.h"
#include <string>
#include <vector>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <list>
using std::string;
using std::wstring;
using std::pair;
using std::vector;
using std::map;
using std::set;
using std::unordered_set;
using std::unordered_map;
using std::list;
static map<string, pair<set<int>, set<SAPFOR::Argument*>>> outForFunc;
static unordered_map<SgSymbol*, string> global_cache, local_cache;
static unordered_map <SAPFOR::Argument*, SgSymbol*> argumentToSymbol;
#define DEBUG_PRINT_PRIVATE 0
#define PRINT_PRIVATES 1
#define PRINT_WARNINGS 1
// print privates and lastprivates for loop
void printLoopInfo(const LoopGraph* loop)
{
SgForStmt* loop_stmt = isSgForStmt(loop->loop);
const set<string>& priv = loop->privateScalars;
const set<string>& lastpriv = loop->lastprivateScalars;
if(!loop_stmt)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
__spf_print(PRINT_PRIVATES, " loop in file '%s' at line %d\n", loop->fileName.c_str(), loop->lineNum);
__spf_print(PRINT_PRIVATES, " privates:");
for(const auto& ident : priv)
__spf_print(PRINT_PRIVATES, " %s", ident.c_str());
__spf_print(PRINT_PRIVATES, "\n lastprivates:");
for (const auto& ident : lastpriv)
__spf_print(PRINT_PRIVATES, " %s", ident.c_str());
__spf_print(PRINT_PRIVATES, "\n");
if (PRINT_WARNINGS)
{
set<string> added;
for (auto& data : getAttributes<SgStatement*, SgStatement*>(loop_stmt, set<int>{ SPF_ANALYSIS_DIR }))
fillPrivatesFromComment(new Statement(data), added);
set<string> extra_old;
std::set_difference(added.begin(), added.end(), priv.begin(), priv.end(), std::inserter(extra_old, extra_old.begin()));
if (extra_old.size() != 0)
{
__spf_print(PRINT_WARNINGS, " [WARNING] extra private variables:");
for (const auto& ident : extra_old)
__spf_print(PRINT_WARNINGS, " %s", ident.c_str());
__spf_print(PRINT_WARNINGS, "\n");
}
}
}
// check if parent statement contains stmt
static bool isParentStmt(SgStatement* stmt, SgStatement* parent)
{
for (; stmt; stmt = stmt->controlParent())
if (stmt == parent)
return true;
return false;
}
// iterate over expr tree and find SgSymbol that matches arg (by name)
static SgSymbol* findSymbolByArgInExpression(const vector<pair<const Variable*, CommonBlock*>>& commonVars,
const FuncInfo* func, const SAPFOR::Argument* arg, SgExpression* expr)
{
if (!expr)
return NULL;
if (expr->symbol() && expr->symbol()->identifier() && getArgNameBySymbol(commonVars, func, expr->symbol(), global_cache, local_cache) == arg->getValue())
return expr->symbol();
SgSymbol* left;
if (left = findSymbolByArgInExpression(commonVars, func, arg, expr->lhs()))
return left;
return findSymbolByArgInExpression(commonVars, func, arg, expr->rhs());
}
// find SgSymbol that matches arg (by name) in stmt
static SgSymbol* findSymbolByArgInStatement(const vector<pair<const Variable*, CommonBlock*>>& commonVars,
const FuncInfo* func, const SAPFOR::Argument* arg, SgStatement* stmt)
{
if (!stmt)
return NULL;
if (stmt->hasSymbol() && stmt->symbol() &&
getArgNameBySymbol(commonVars, func, stmt->symbol(), global_cache, local_cache) == arg->getValue())
{
return stmt->symbol();
}
for (int i = 0; i < 3; i++)
{
SgSymbol* found = findSymbolByArgInExpression(commonVars, func, arg, stmt->expr(i));
if (found)
return found;
}
return NULL;
}
// find SgSymbol for arg in instr's operator and fill argumentToSymbol
// do nothing if arg already has found symbol
static void addPlaceWithDef(const vector<pair<const Variable*, CommonBlock*>>& commonVars,
const FuncInfo* func, SAPFOR::Argument* arg, SAPFOR::Instruction* instr) {
if (argumentToSymbol.find(arg) != argumentToSymbol.end())
return;
SgStatement* stmt_with_decl = instr->getOperator();
if (!stmt_with_decl)
return;
SgSymbol* found = findSymbolByArgInStatement(commonVars, func, arg, stmt_with_decl);
if (found)
argumentToSymbol[arg] = found;
}
static void getDefined(const string& func, const vector<SAPFOR::Argument*>& params,
set<SAPFOR::Argument*>& result)
{
if (!joinGlobalsWithParameters(params, outForFunc, func, result))
{
if (func == string("_WRITE") || isIntrinsic(func.c_str()))
return;
else //READ or else
insertIfVar(params.begin(), params.end(), result);
}
}
static void fillOutForFunc(const FuncInfo* func, const vector<SAPFOR::BasicBlock*>& blocks)
{
if (blocks.size() == 0)
return;
set<SAPFOR::BasicBlock*> exits = {};
for (auto block : blocks)
{
if (block->getNext().size() == 0)
exits.insert(block);
}
set<int> defined;
set<SAPFOR::Argument*> common_defined;
for (auto byExit : exits)
{
for (const auto& byRd : byExit->getRD_Out())
{
auto out_arg = byRd.first;
if (!(byRd.second.size() == 1 && *(byRd.second.begin()) < 0))
{
switch (out_arg->getMemType())
{
case SAPFOR::CFG_MEM_TYPE::COMMON_:
case SAPFOR::CFG_MEM_TYPE::MODULE_:
common_defined.insert(out_arg);
break;
case SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_:
{
int num = getParamIndex(out_arg, func->funcParams.countOfPars);
if(func->funcParams.isArgOut(num))
defined.insert(num);
break;
}
}
}
}
}
outForFunc[func->funcName] = { defined, common_defined };
}
static void getDefsFromBlock(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& res,
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
const FuncInfo* func)
{
vector<SAPFOR::Argument*> lastParamRef;
for (auto ir_block : block->getInstructions())
{
SAPFOR::Instruction* instr = ir_block->getInstruction();
SAPFOR::CFG_OP instr_operation = instr->getOperation();
if (instr_operation == SAPFOR::CFG_OP::PARAM)
{
SAPFOR::Argument* arg = instr->getArg1();
if(arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
addPlaceWithDef(commonVars, func, arg, instr);
lastParamRef.push_back(arg);
}
else if (instr_operation == SAPFOR::CFG_OP::F_CALL)
{
int count = stoi(instr->getArg2()->getValue());
if (lastParamRef.size() != count)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const string& fName = instr->getArg1()->getValue();
getDefined(fName, lastParamRef, res);
lastParamRef.clear();
}
}
int first_instr_num = block->getInstructions().front()->getNumber();
int last_instr_num = block->getInstructions().back()->getNumber();
for (const auto& def : block->getRD_Out())
for (int place : def.second)
if (place >= first_instr_num && place <= last_instr_num && def.first->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
{
res.insert(def.first);
addPlaceWithDef(commonVars, func, def.first, block->getInstructions()[place - first_instr_num]->getInstruction());
}
}
// recursively analyze FOR loops
static set<SAPFOR::BasicBlock*> analyzeLoop(LoopGraph* loop, const set<SAPFOR::BasicBlock*>& blocks,
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
const map<string, SgSymbol*>& commonArgs, FuncInfo* func,
map<string, vector<Messages>>& messages)
{
if (!loop->isFor)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__); //should be called only with FOR loops
SgStatement* loop_operator = loop->loop->GetOriginal();
// find blocks related to the current loop
set<SAPFOR::BasicBlock*> currentLoop = { };
/*
service block that looks like
_reg = _reg < _reg
IF_FALSE _reg then goto ...
*/
SAPFOR::BasicBlock* head_block = NULL;
int loop_start = loop->lineNum, loop_end = loop->lineNumAfterLoop;
for (auto bb : blocks)
{
if (!bb || (bb->getInstructions().size() == 0))
continue;
SgStatement* first = bb->getInstructions().front()->getInstruction()->getOperator();
SgStatement* last = bb->getInstructions().back()->getInstruction()->getOperator();
if (isParentStmt(first, loop_operator) && isParentStmt(last, loop_operator))
{
currentLoop.insert(bb);
if ((!head_block) && (first == loop_operator) && (last == loop_operator) &&
(bb->getInstructions().size() == 2) &&
(bb->getInstructions().back()->getInstruction()->getOperation() == SAPFOR::CFG_OP::JUMP_IF))
{
head_block = bb;
}
}
}
if (!head_block)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
// find blocks inside loop wich can lead to head_block
list<SAPFOR::BasicBlock*> search_stack = { head_block };
set<SAPFOR::BasicBlock*> cycleBody = { };
while (search_stack.size() > 0)
{
SAPFOR::BasicBlock* curr = search_stack.front();
search_stack.pop_front();
if (cycleBody.insert(curr).second)
for (auto next : curr->getPrev())
if (currentLoop.count(next))
search_stack.push_back(next);
}
set<SAPFOR::Argument*> useValueInLoop = {};
for (const auto& use : head_block->getLiveIn())
{
for (SAPFOR::BasicBlock* place : use.second)
{
if (currentLoop.count(place))
{
useValueInLoop.insert(use.first);
break;
}
}
}
set<SAPFOR::Argument*> changeValueInLoop = { };
set<SAPFOR::Argument*> changeValueOnExit = { };
set<SAPFOR::Argument*> LiveWhenLoopEnds = { };
auto loop_it = currentLoop.begin();
auto loop_end_it = currentLoop.end();
auto body_it = cycleBody.begin();
auto body_end = cycleBody.end();
while ((loop_it != loop_end_it) && (body_it != body_end))
{
if (*loop_it == *body_it)
{
getDefsFromBlock(*loop_it, changeValueInLoop, commonVars, func);
body_it++;
}
else
getDefsFromBlock(*loop_it, changeValueOnExit, commonVars, func);
loop_it++;
}
if (body_it != body_end)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (; loop_it != loop_end_it; loop_it++)
getDefsFromBlock(*loop_it, changeValueOnExit, commonVars, func);
for (auto bb : currentLoop)
{
//fill LiveWhenLoopEnds
bool has_next_outside_body = false;
for (const auto& next : bb->getNext())
{
if (cycleBody.find(next) == cycleBody.end())
{
has_next_outside_body = true;
break;
}
}
if (has_next_outside_body)
{
for (const auto& use : bb->getLiveOut())
for (SAPFOR::BasicBlock* place : use.second)
if (currentLoop.count(place) == 0)
{
LiveWhenLoopEnds.insert(use.first);
break;
}
}
}
set<SAPFOR::Argument*> arg_private = {}, arg_lastprivate = {};
std::set_difference(changeValueInLoop.begin(), changeValueInLoop.end(),
useValueInLoop.begin(), useValueInLoop.end(),
std::inserter(arg_private, arg_private.begin()));
arg_private.insert(changeValueOnExit.begin(), changeValueOnExit.end());
std::set_intersection(arg_private.begin(), arg_private.end(),
LiveWhenLoopEnds.begin(), LiveWhenLoopEnds.end(),
std::inserter(arg_lastprivate, arg_lastprivate.begin()));
changeValueInLoop.clear();
LiveWhenLoopEnds.clear();
useValueInLoop.clear();
vector<const depNode*> sym_private;
for (auto e : arg_private)
{
SgSymbol* arg_sym = NULL;
auto it = argumentToSymbol.find(e);
if (it != argumentToSymbol.end())
arg_sym = it->second;
else if (e->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || e->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
continue;
if (arg_sym && arg_sym->identifier())
{
if (arg_lastprivate.find(e) != arg_lastprivate.end())
{
loop->lastprivateScalars.insert(arg_sym->identifier());
const char* identifier = arg_sym->identifier();
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"add lastprivate scalar '%s' to loop on line %d", to_wstring(identifier).c_str(), loop->lineNum);
__spf_printToLongBuf(messageR, R200, to_wstring(identifier).c_str(), loop->lineNum);
messages[loop->fileName].push_back(Messages(NOTE, loop->lineNum, messageR, messageE, 3002));
}
else
{
SgStatement* s = new SgStatement(0);
s->setlineNumber(loop_start);
SgExpression* exp = new SgExpression(VAR_REF);
exp->setSymbol(arg_sym);
sym_private.push_back(new depNode(s, s, exp, exp, 0, 0, NULL, NULL, 0));
loop->privateScalars.insert(arg_sym->identifier());
}
}
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
addPrivatesToLoops(loop, sym_private, { {loop_start, isSgForStmt(loop_operator)} }, messages[loop->fileName]);
for (const depNode* node : sym_private)
{
delete node->stmtin;
delete node;
}
arg_private.clear();
arg_lastprivate.clear();
printLoopInfo(loop);
return currentLoop;
}
static void recAnalyzeLoop(LoopGraph* loop, const set<SAPFOR::BasicBlock*>& blocks,
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
const map<string, SgSymbol*>& commonArgs,
FuncInfo* func, map<string, vector<Messages>>& messages)
{
const auto& loop_body = loop->isFor ? analyzeLoop(loop, blocks, commonVars, commonArgs, func, messages) : blocks;
for (const auto& inner_loop : loop->children)
recAnalyzeLoop(inner_loop, loop_body, commonVars, commonArgs, func, messages);
}
void runPrivateVariableAnalysis(const map<string, vector<LoopGraph*>>& loopGraph,
const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project,
const map<string, CommonBlock*>& commonBlocks,
map<string, vector<Messages>>& messages)
{
map<string, FuncInfo*> funcByName;
for (const auto& byFunc : CFGraph_for_project)
if (byFunc.first)
funcByName[byFunc.first->funcName] = byFunc.first;
//fill outForFunc
for (const auto& byLoopFunc : loopGraph)
{
for (const auto& byLoop : byLoopFunc.second)
{
for (const auto& byFuncCall : byLoop->calls)
{
const string& fname = byFuncCall.first;
if (outForFunc.find(fname) == outForFunc.end())
{
auto func_it = funcByName.find(fname);
if (func_it != funcByName.end())
{
FuncInfo* func = func_it->second;
auto cfg_it = CFGraph_for_project.find(func);
if (cfg_it == CFGraph_for_project.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
fillOutForFunc(cfg_it->first, cfg_it->second);
}
}
}
}
}
map<FuncInfo*, map<string, SgSymbol*>> commonArgsByFunc = { };
for (const auto& byFile : loopGraph)
{
SgFile::switchToFile(byFile.first);
for (auto loop : byFile.second)
{
int loop_start = loop->lineNum, loop_end = loop->lineNumAfterLoop;
SgStatement* search_func = loop->loop->GetOriginal();
while (search_func && (!isSgProgHedrStmt(search_func)))
search_func = search_func->controlParent();
if(!search_func)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__); //loop statement outside any function statement
bool loop_analyzed = false;
for (const auto& byFunc : CFGraph_for_project)
{
if (byFunc.first->fileName == byFile.first && byFunc.first->funcPointer->GetOriginal() == search_func)
{
const auto& commonVars = getCommonsByFunction(current_file, byFunc.first->funcPointer, commonBlocks);
const auto& commonArgs = getCommonArgsByFunc(byFunc.first, commonArgsByFunc, commonVars, global_cache, local_cache);
set<SAPFOR::BasicBlock*> loop_ir;
loop_ir.insert(byFunc.second.begin(), byFunc.second.end());
recAnalyzeLoop(loop, loop_ir, commonVars, commonArgs, byFunc.first, messages);
argumentToSymbol.clear(); //clear cache
loop_analyzed = true;
break;
}
}
if(!loop_analyzed)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__); //no func found for loop
}
local_cache.clear();
commonArgsByFunc.clear();
}
outForFunc.clear();
global_cache.clear();
}

View File

@@ -0,0 +1,11 @@
#include "../Utils/SgUtils.h"
#include "../GraphLoop/graph_loops.h"
#include "CFGraph.h"
#include <string>
#include <map>
void runPrivateVariableAnalysis(const std::map<std::string, std::vector<LoopGraph*>>& loopGraph,
const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project,
const std::map<std::string, CommonBlock*>& commonBlocks,
std::map<std::string, std::vector<Messages>>& messages);

View File

@@ -0,0 +1,882 @@
#include "CreateInterTree.h"
#include "../Utils/SgUtils.h"
#include "../Utils/utils.h"
#include "../GraphCall/graph_calls_func.h"
using std::string;
using std::wstring;
using std::vector;
using std::list;
using std::map;
using std::pair;
using std::set;
using std::cout;
using std::endl;
using std::fstream;
static long int getNextTag()
{
static long int INTERVAL_TAG = 0;
return INTERVAL_TAG++;
}
//Debug funcs
static void printTree(SpfInterval* inter, fstream &file, int level)
{
if (!(inter->ifInclude))
{
for (int i = 0; i < inter->nested.size(); i++)
printTree(inter->nested[i], file, level + 1);
return;
}
if (!inter->begin->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int i = 0; i < level; i++)
file << " ";
file << " Begin INTERVAL #" << inter->tag << " (var " << tag[inter->begin->variant()];
if (inter->begin->variant() == PROC_HEDR || inter->begin->variant() == FUNC_HEDR)
{
string name(inter->begin->symbol()->identifier());
convertToUpper(name);
file << ", " << name;
}
file << ", gcov_calls " << inter->calls_count << ") ";
file << " [" << inter->lineFile.first << ", " << inter->lineFile.second << "]";
if (inter->parent == NULL && level != 0)
file << " -- through PROC_CALL --";
file << "\n";
for (int i = 0; i < inter->nested.size(); i++)
printTree(inter->nested[i], file, level + 1);
for (int i = 0; i < inter->ends.size(); i++)
{
for (int i = 0; i < level; i++)
file << " ";
file << " End INTERVAL #" << inter->tag << " (exit lvl " << inter->exit_levels[i] << ", var " << tag[inter->ends[i]->variant()] << ") ";
file << "line " << inter->ends[i]->lineNumber() << endl;
}
if (level == 0)
file << endl;
}
void saveIntervals(const string &fileName, map<string, vector<SpfInterval*>> &intervals)
{
fstream file_intervals;
file_intervals.open(fileName, fstream::out);
for (auto &byfile : intervals)
{
file_intervals << "**** INTERVALS FOR FILE '" << byfile.first << "'\n";
for (auto &interval : byfile.second)
printTree(interval, file_intervals, 0);
}
file_intervals.close();
}
//Labels funcs
static void matchGotoLabels(SgStatement *st, map<int, vector<int>> &gotoStmts)
{
map<int, vector<int>> labelsRef;
findAllRefsToLables(st, labelsRef, false);
for (auto &key : labelsRef)
for (auto &it : key.second)
gotoStmts[it].push_back(key.first);
}
static void findAllLabels(SgStatement* st, map<int, int> &labelsRef)
{
SgStatement* end = st->lastNodeOfStmt();
while (st != end)
{
if (st->hasLabel())
labelsRef[st->label()->id()] = st->lineNumber();
st = st->lexNext();
}
if (end->hasLabel())
labelsRef[end->label()->id()] = end->lineNumber();
}
//Nested intervals removal
static int getNestedLevel(SgStatement* loop_stmt)
{
int depth = 0;
SgStatement *current_loop = loop_stmt->lexNext();
SgStatement* controlEnd = loop_stmt->lastNodeOfStmt()->lexPrev();
SgStatement *controlEnd2 = current_loop->lastNodeOfStmt();
while (isSgForStmt(current_loop) && isSgControlEndStmt(controlEnd) && controlEnd == controlEnd2)
{
current_loop = current_loop->lexNext();
controlEnd = controlEnd->lexPrev();
controlEnd2 = current_loop->lastNodeOfStmt();
depth++;
}
return depth;
}
static void removeNestedIntervals(SpfInterval* interval)
{
if (isSgForStmt(interval->begin))
{
int depth = getNestedLevel(interval->begin);
SpfInterval *current_interval = interval;
for (int i = 0; i < depth; i++)
{
current_interval = current_interval->nested[0];
current_interval->ifInclude = false;
}
}
for (auto &include : interval->nested)
removeNestedIntervals(include);
}
// Merge trees functions.
static int compareIntervals(SpfInterval* interval1, SpfInterval* interval2)
{
SgStatement* begin_st_1 = interval1->begin;
while (!isSgExecutableStatement(begin_st_1) || isSPF_stat(begin_st_1) || isDVM_stat(begin_st_1))
begin_st_1 = begin_st_1->lexNext();
SgStatement* begin_st_2 = interval2->begin;
while (!isSgExecutableStatement(begin_st_2) || isSPF_stat(begin_st_2) || isDVM_stat(begin_st_2))
begin_st_2 = begin_st_2->lexNext();
int begin_1 = begin_st_1->lineNumber();
int begin_2 = begin_st_2->lineNumber();
int end_1 = interval1->ends[0]->lineNumber();
int end_2 = interval2->ends[0]->lineNumber();
if((begin_1 == begin_2 && end_1 == end_2) || end_1 <= begin_2 || begin_1 >= end_2)
return 0;
if(begin_1 <= begin_2 && end_1 >= end_2)
return 1;
return -1;
}
static void insertIntervalIntoTree(vector<SpfInterval*> &tree, SpfInterval* userInterval)
{
bool ifDeleteNested = false;
for(int i = 0; i < tree.size(); i++)
{
int compare_result = compareIntervals(tree[i], userInterval);
if(compare_result == 0)
continue;
if(compare_result > 0)
{
int amount = 0;
for(int j = 1; j < tree[i]->ends.size(); j++)
{
int endLineNumber = tree[i]->ends[j]->lineNumber();
if(endLineNumber >= userInterval->begin->lineNumber() && endLineNumber <= userInterval->ends[0]->lineNumber())
{
userInterval->ends.push_back(tree[i]->ends[j]);
userInterval->exit_levels.push_back(0);
tree[i]->ends[j] = NULL;
amount++;
}
}
tree[i]->ends.erase(std::remove_if(tree[i]->ends.begin(), tree[i]->ends.end(), [](SgStatement* stmt) {return (stmt == NULL);}), tree[i]->ends.end());
for(int j = 0; j < amount; j++)
tree[i]->exit_levels.pop_back();
insertIntervalIntoTree(tree[i]->nested, userInterval);
return;
}
userInterval->nested.push_back(tree[i]);
userInterval->parent = tree[i]->parent;
tree[i]->parent = userInterval;
tree[i] = userInterval;
if(ifDeleteNested)
tree[i] = NULL;
else
ifDeleteNested = true;
}
tree.erase(std::remove_if(tree.begin(), tree.end(), [](SpfInterval* interval) {return (interval == NULL);}), tree.end());
}
static void mergeTrees(vector<SpfInterval*> &fileIntervals, vector<SpfInterval*> &userIntervals)
{
for(auto &userInterval : userIntervals)
insertIntervalIntoTree(fileIntervals, userInterval);
}
// Calibrate interval exits.
static void calibrateExits(const vector<SpfInterval*>& fileIntervals, const map<int, int> &labelsRef, map<int, vector<int>> &gotoStmts, int level)
{
for(auto &interval : fileIntervals)
{
for(int i = 1; i < interval->ends.size(); i++)
{
int variant = interval->ends[i]->variant();
int &exit_level = interval->exit_levels[i];
if (variant == RETURN_STAT || variant == STOP_STAT || variant == EXIT_STMT)
exit_level = level;
if (variant == EXIT_STMT)
exit_level = 1;
for (auto&lab : gotoStmts[interval->ends[i]->lineNumber()])
{
auto itL = labelsRef.find(lab);
if (itL == labelsRef.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const int label_line = itL->second;
if (label_line == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
int depth = 0;
SpfInterval* searchInterval = interval;
while (label_line < searchInterval->begin->lineNumber() || label_line > searchInterval->ends[0]->lineNumber())
{
searchInterval = searchInterval->parent;
depth++;
if (searchInterval == NULL)
break;
}
exit_level = depth;
}
}
calibrateExits(interval->nested, labelsRef, gotoStmts, level + 1);
}
}
static void removeUserIntervals(SgFile *file)
{
for (SgStatement* st = file->firstStatement(); st; st = st->lexNext())
{
const int var = st->variant();
if (var == DVM_INTERVAL_DIR || var == DVM_EXIT_INTERVAL_DIR || var == DVM_ENDINTERVAL_DIR)
{
//move comment to next statement
if (st->comments())
{
const char* comms = st->comments();
string comments(comms);
st->delComments();
SgStatement* next = st->lexNext();
if (next)
next->addComment(comments.c_str());
}
st = st->lexPrev();
st->lexNext()->deleteStmt();
}
}
}
// Find intervals functions.
static void findUserIntervals(SgStatement *startSt, vector<SpfInterval*> &userIntervals, vector<Messages> &messages)
{
SpfInterval *currentInterval = NULL;
SgStatement *endSt = startSt->lastNodeOfStmt();
SgStatement *currentSt = startSt;
set<SpfInterval*> userIntervalsSet;
while (currentSt != endSt)
{
if(currentSt->variant() == DVM_INTERVAL_DIR)
{
SgStatement* begin = currentSt;
while (isDVM_stat(begin))
begin = begin->lexNext();
SpfInterval *inter = new SpfInterval(currentSt->lineNumber());
inter->begin = begin;
inter->lineFile = std::make_pair(begin->lineNumber(), begin->fileName());
inter->parent = currentInterval;
inter->tag = getNextTag();
userIntervals.push_back(inter);
currentInterval = inter;
userIntervalsSet.insert(currentInterval);
}
if(currentSt->variant() == DVM_ENDINTERVAL_DIR)
{
if (currentInterval == NULL)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
SgStatement* end = currentSt;
while(isDVM_stat(end))
end = end->lexPrev();
currentInterval->ends.push_back(end);
currentInterval->exit_levels.push_back(0);
currentInterval = currentInterval->parent;
}
currentSt = currentSt->lexNext();
}
bool error = false;
//check for ends
for (auto& inter : userIntervalsSet)
{
if (inter->begin == NULL)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (inter->ends.size() == 0)
{
wstring messageR, messageE;
__spf_printToLongBuf(messageE, L"Can not find end of DVM's interval");
__spf_printToLongBuf(messageR, R150);
messages.push_back(Messages(ERROR, inter->userIntervalLine, messageR, messageE, 1052));
error = true;
}
}
if (error)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
static void findIntervals(SpfInterval *interval, map<int, int> &labelsRef, map<int, vector<int>> &gotoStmts, SgStatement *&currentSt)
{
int currentVar = -1;
SgStatement* endStatement = interval->parent ? interval->ends[0] : interval->begin->lastNodeOfStmt();
while (currentSt != endStatement && currentVar != CONTAINS_STMT)
{
currentSt = currentSt->lexNext();
currentVar = currentSt->variant();
if (currentSt->fileName() != string(interval->begin->fileName()))
continue;
if (currentVar == RETURN_STAT || currentVar == STOP_STAT || currentVar == EXIT_STMT || currentVar == CONTAINS_STMT)
{
if (endStatement != currentSt)
{
interval->ends.push_back(currentSt);
interval->exit_levels.push_back(0);
}
}
if (gotoStmts.find(currentSt->lineNumber()) != gotoStmts.end() && currentVar != LOGIF_NODE)
{
vector<int>& labels = gotoStmts[currentSt->lineNumber()];
for (auto& lab : labels)
{
auto itL = labelsRef.find(lab);
if (itL == labelsRef.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const int label_line = itL->second;
if (label_line == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (label_line < interval->begin->lineNumber() || label_line > interval->ends[0]->lineNumber())
{
interval->ends.push_back(currentSt);
interval->exit_levels.push_back(0);
}
}
}
if (currentSt == endStatement || currentVar != FOR_NODE)
continue;
SpfInterval* inter = new SpfInterval(-1);
inter->begin = currentSt;
inter->ends.push_back(currentSt->lastNodeOfStmt());
inter->lineFile = std::make_pair(currentSt->lineNumber(), currentSt->fileName());
inter->parent = interval;
inter->exit_levels.push_back(0);
inter->tag = getNextTag();
interval->nested.push_back(inter);
findIntervals(inter, labelsRef, gotoStmts, currentSt);
}
}
void createInterTree(SgFile *file, vector<SpfInterval*> &fileIntervals, bool nested_on, vector<Messages> &messages)
{
int funcNum = file->numberOfFunctions();
for (int i = 0; i < funcNum; i++)
{
map<int, int> labelsRef; // id => line
map<int, vector<int>> gotoStmts; // line => label_ids
vector<SpfInterval*> userIntervals;
// Find labels.
findAllLabels(file->functions(i), labelsRef);
matchGotoLabels(file->functions(i), gotoStmts);
// Find user intervals.
findUserIntervals(file->functions(i), userIntervals, messages);
SpfInterval *func_inters = new SpfInterval(-1);
// Set begining of the interval.
func_inters->begin = file->functions(i);
func_inters->lineFile = std::make_pair(func_inters->begin->lineNumber(), file->functions(i)->fileName());
func_inters->tag = getNextTag();
// Set ending of the interval.
SgStatement *lastNode = func_inters->begin->lastNodeOfStmt()->lexPrev();
while (isDVM_stat(lastNode) || isSPF_stat(lastNode))
lastNode = lastNode->lexPrev();
SgStatement *prevLastNode = lastNode->lexPrev();
while (isDVM_stat(prevLastNode) || isSPF_stat(prevLastNode))
prevLastNode = prevLastNode->lexPrev();
if (lastNode->variant() == RETURN_STAT || lastNode->variant() == EXIT_STMT || lastNode->variant() == STOP_STAT)
{
bool cond = false;
if (lastNode->lexNext()->variant() == CONTROL_END)
if (isSgProgHedrStmt(lastNode->lexNext()->controlParent()))
cond = true;
if (cond)
func_inters->ends.push_back(lastNode);
else
func_inters->ends.push_back(prevLastNode);
}
else
func_inters->ends.push_back(lastNode);
func_inters->exit_levels.push_back(0);
// Find inner intervals.
SgStatement *currentSt = func_inters->begin;
findIntervals(func_inters, labelsRef, gotoStmts, currentSt);
vector<SpfInterval*> oneInterval;
oneInterval.push_back(func_inters);
mergeTrees(oneInterval, userIntervals);
calibrateExits(oneInterval, labelsRef, gotoStmts, 1);
fileIntervals.push_back(oneInterval[0]);
}
if (nested_on)
for (auto &interval : fileIntervals)
removeNestedIntervals(interval);
}
//SpfInterval insertion funcs
static void insertTree(SpfInterval* interval, const string &fileName)
{
if (interval->ifInclude && interval->begin->fileName() == fileName)
{
SgStatement* beg_inter = new SgStatement(DVM_INTERVAL_DIR);
SgExpression* expr = new SgValueExp(interval->tag);
beg_inter->setExpression(0, *expr);
SgStatement* end_inter = new SgStatement(DVM_ENDINTERVAL_DIR);
// Skip to executables.
SgStatement* beginSt = interval->begin;
while (!isSgExecutableStatement(beginSt) || isSPF_stat(beginSt) || isDVM_stat(beginSt))
beginSt = beginSt->lexNext();
if (beginSt->lexPrev()->variant() == LOGIF_NODE)
LogIftoIfThen(beginSt->lexPrev());
// Insert begining
beginSt->insertStmtBefore(*beg_inter, *beginSt->controlParent());
beg_inter->setlineNumber(beginSt->lineNumber());
interval->ends[0]->insertStmtAfter(*end_inter, *beginSt->controlParent());
for (int i = 1; i < interval->ends.size(); i++)
{
int depth = interval->exit_levels[i];
SpfInterval* curr_inter = interval->parent;
SgExprListExp* expli = new SgExprListExp(*(new SgValueExp(interval->tag)));
SgExprListExp* curr_list_elem = expli;
for (int j = 1; j < depth; j++)
{
if(curr_inter->ifInclude)
{
curr_list_elem->setRhs(new SgExprListExp(*(new SgValueExp(curr_inter->tag))));
curr_list_elem = curr_list_elem->next();
}
curr_inter = curr_inter->parent;
}
curr_list_elem->setRhs(NULL);
SgStatement* exit_inter = new SgStatement(DVM_EXIT_INTERVAL_DIR);
exit_inter->setExpression(0, *expli);
if (interval->ends[i]->lexPrev()->variant() == LOGIF_NODE)
LogIftoIfThen(interval->ends[i]->lexPrev());
interval->ends[i]->insertStmtBefore(*exit_inter, *interval->ends[i]->controlParent());
}
}
for (int i = 0; i < interval->nested.size(); i++)
insertTree(interval->nested[i], fileName);
}
void insertIntervals(SgFile *file, const vector<SpfInterval*> &fileIntervals)
{
const string currFile = file->filename();
removeUserIntervals(file);
for (auto &interval : fileIntervals)
insertTree(interval, currFile);
}
//Profiling funcs
static map<int, long long> parseProfiles(fstream &file)
{
map<int, long long> fileProfile;
string line;
while (!file.eof())
{
getline(file, line);
auto pos_type = line.find(":");
string type = line.substr(0, pos_type);
if (type == "lcount")
{
if ((int)line.size() >= pos_type + 1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
string nums = line.substr(pos_type + 1);
auto pos_com = nums.find(",");
auto line_num = stoi(nums.substr(0, pos_com));
if ((int)nums.size() >= pos_com + 1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
long long calls_num = stoll(nums.substr(pos_com + 1));
fileProfile[line_num] = calls_num;
}
}
return fileProfile;
}
static void assignRec(SpfInterval* inter, map<int, long long> &fp)
{
for (int i = 0; i < inter->nested.size(); i++)
assignRec(inter->nested[i], fp);
inter->calls_count = fp[inter->begin->lineNumber()];
}
void assignCallsToFile(const string &baseFilename, vector<SpfInterval*> &intervals)
{
fstream file;
file.open(baseFilename + ".gcov", fstream::in);
if (!file.good())
return;
map<int, long long> fileProfile = parseProfiles(file);
file.close();
for (auto &interval : intervals)
assignRec(interval, fileProfile);
}
//Deleting intervals funcs
static void removeNode(SpfInterval* inter, long long threshold)
{
if (inter->calls_count >= threshold)
inter->ifInclude = false;
for (int i = 0; i < inter->nested.size(); i++)
removeNode(inter->nested[i], threshold);
}
static void fillListWithValues(list<long long> &interval_calls, SpfInterval* interval)
{
auto it = interval_calls.begin();
for(; it != interval_calls.end(); it++)
if(interval->calls_count < *it)
{
interval_calls.insert(it, interval->calls_count);
break;
}
if(it == interval_calls.end())
interval_calls.push_back(interval->calls_count);
for (auto &i : interval->nested)
fillListWithValues(interval_calls, i);
}
void removeNodes(int threshold, vector<SpfInterval*> &intervals, vector<string> &include_functions)
{
if (threshold == 100)
return;
for (auto &interval : intervals)
{
string func_name = interval->begin->symbol()->identifier();
if (find(include_functions.begin(), include_functions.end(), func_name) != include_functions.end())
continue;
list<long long> interval_calls;
fillListWithValues(interval_calls, interval);
int amount = interval_calls.size() / 100.f * threshold;
auto it = interval_calls.begin();
advance(it, amount);
removeNode(interval, *it);
}
}
void createMapOfinterval(map<int, SpfInterval*> &mapIntervals, const vector<SpfInterval*> &intervals)
{
for (auto &inter : intervals)
{
auto it = mapIntervals.find(inter->begin->lineNumber());
if (it != mapIntervals.end())
continue;
mapIntervals[inter->begin->lineNumber()] = inter;
createMapOfinterval(mapIntervals, inter->nested);
}
}
void initTimeForIntervalTree(const int numOfTopologies, vector<SpfInterval*> &intervals)
{
for (auto &inter : intervals)
{
inter->predictedTimes.resize(numOfTopologies);
inter->predictedRemoteTimes.resize(numOfTopologies);
std::fill(inter->predictedTimes.begin(), inter->predictedTimes.end(), -1);
std::fill(inter->predictedRemoteTimes.begin(), inter->predictedRemoteTimes.end(), 0);
initTimeForIntervalTree(numOfTopologies, inter->nested);
}
}
void aggregatePredictedTimes(vector<SpfInterval*> &itervals)
{
for (auto &interval : itervals)
{
if (interval->predictedTimes.size() && interval->predictedTimes[0] != -1)
continue;
if (interval->nested.size())
aggregatePredictedTimes(interval->nested);
for (int topo = 0; topo < interval->predictedTimes.size(); ++topo)
{
double newTimeSum = 0;
for (auto &nestedI : interval->nested)
{
if (nestedI->predictedTimes[topo] == -1)
newTimeSum += nestedI->exec_time + nestedI->predictedRemoteTimes[topo];
else
newTimeSum += nestedI->predictedTimes[topo] + nestedI->predictedRemoteTimes[topo];
}
interval->predictedTimes[topo] = newTimeSum;
}
}
}
SpfInterval* getMainInterval(SgProject *project, const map<string, vector<SpfInterval*>> &intervals, map<string, vector<Messages>> &SPF_messages)
{
SgStatement *mainUnit = findMainUnit(project, SPF_messages);
SpfInterval *mainIterval = NULL;
checkNull(mainUnit, convertFileName(__FILE__).c_str(), __LINE__);
auto itMainVec = intervals.find(mainUnit->fileName());
if (itMainVec == intervals.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (itMainVec->second.size() == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
else if (itMainVec->second.size() > 1)
{
for (auto &elem : itMainVec->second)
if (elem->begin->variant() == PROG_HEDR)
mainIterval = elem;
checkNull(mainIterval, convertFileName(__FILE__).c_str(), __LINE__);
}
else
mainIterval = itMainVec->second[0];
return mainIterval;
}
SpfInterval* findNearestUp(const map<SgStatement*, SpfInterval*> &intervals, SgStatement *st)
{
SpfInterval *found = NULL;
while (st)
{
auto it = intervals.find(st);
if (it != intervals.end())
{
found = it->second;
break;
}
else
st = st->controlParent();
}
checkNull(found, convertFileName(__FILE__).c_str(), __LINE__);
return found;
}
SpfInterval* findNearestDown(const map<SgStatement*, SpfInterval*> &intervals, SgStatement *st)
{
SpfInterval *found = NULL;
while (st)
{
auto it = intervals.find(st);
if (it != intervals.end())
{
found = it->second;
break;
}
else
st = st->lexNext();
}
checkNull(found, convertFileName(__FILE__).c_str(), __LINE__);
return found;
}
static FuncInfo* getFunc(const string &file, const int line, const map<string, FuncInfo*> &allFuncs)
{
for (auto &func : allFuncs)
if (func.second->linesNum.first == line && func.second->fileName == file)
return func.second;
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return NULL;
}
static void createMapOfIntervals(const vector<SpfInterval*> &intervals, map<SgStatement*, SpfInterval*> &intervalsBySt)
{
for (auto &interval : intervals)
intervalsBySt[interval->begin] = interval;
for (auto &interval : intervals)
if (interval->nested.size())
createMapOfIntervals(interval->nested, intervalsBySt);
}
static void insertAndSort(SpfInterval *nearest, SpfInterval *toInsert, SgStatement *stLine)
{
if (nearest->nested.size() == 0)
nearest->nested.push_back(toInsert);
else
{
const int line = stLine->lineNumber();
for (int z = 0; z < nearest->nested.size(); ++z)
{
if (nearest->nested[z]->parent)
{
if (nearest->nested[z]->lineFile.first > line)
{
nearest->nested.insert(nearest->nested.begin() + z, toInsert);
return;
}
}
}
nearest->nested.push_back(toInsert);
}
}
void uniteIntervalsBetweenProcCalls(map<string, vector<SpfInterval*>> &intervals, const map<string, vector<FuncInfo*>> &allFuncInfo)
{
map<string, map<SgStatement*, SpfInterval*>> intervalsBySt;
for (auto &byFile : intervals)
createMapOfIntervals(byFile.second, intervalsBySt[byFile.first]);
map<string, FuncInfo*> allFuncs;
createMapOfFunc(allFuncInfo, allFuncs);
for (auto &byFile : intervals)
{
for (auto &intvl : byFile.second)
{
if (intvl->begin->variant() != PROG_HEDR)
{
if (!intvl->begin->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
SgStatement* funcSt = intvl->begin;
if (isSgProgHedrStmt(intvl->begin) == NULL)
funcSt = intvl->begin->controlParent();
const string name = funcSt->symbol()->identifier();
auto currF = getFunc(funcSt->fileName(), funcSt->lineNumber(), allFuncs);
for (auto &callsTo : currF->callsTo)
{
if (SgFile::switchToFile(callsTo->fileName) == -1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (auto &callsInfo: callsTo->callsFromDetailed)
{
auto& callsFrom = callsInfo.pointerDetailCallsFrom;
SgStatement *base = NULL;
if (callsFrom.second == PROC_STAT)
{
base = (SgStatement*)callsFrom.first;
if (base->symbol()->identifier() != name)
base = NULL;
}
else if (callsFrom.second == FUNC_CALL)
{
SgExpression *ex = (SgExpression*)callsFrom.first;
if (ex->symbol()->identifier() == name)
base = SgStatement::getStatmentByExpression(ex);
}
if (base == NULL)
continue;
else
{
auto itI = intervalsBySt.find(callsTo->fileName);
if (itI == intervalsBySt.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto nearest = findNearestUp(itI->second, base);
insertAndSort(nearest, intvl, base);
}
}
}
}
}
}
}

View File

@@ -0,0 +1,75 @@
#pragma once
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <map>
#include "dvm.h"
#include "../GraphLoop/graph_loops_func.h"
struct SpfInterval
{
int userIntervalLine;
int tag = 0;
long long calls_count = 0;
bool ifInclude = true;
bool isRegion;
bool isNested;
SgStatement *begin;
std::pair<int, std::string> lineFile;
SpfInterval *parent;
std::vector<SgStatement*> ends;
std::vector<int> exit_levels;
std::vector<SpfInterval*> nested;
//TODO: to be delete or rewrite with new predictor
//from statistic after execution
int exec_count = 0;
double exec_time = 0;
std::vector<double> predictedTimes;
std::vector<double> predictedRemoteTimes;
SpfInterval(int line)
{
userIntervalLine = line;
begin = NULL;
parent = NULL;
}
int getBestTimeIdx()
{
int idx = -1;
double best = 0;
for (int z = 0; z < predictedTimes.size(); ++z)
{
if (idx == -1 || best > predictedTimes[z])
{
best = predictedTimes[z];
idx = z;
}
}
return idx;
}
};
void saveIntervals(const std::string &fileName, std::map<std::string, std::vector<SpfInterval*>> &intervals);
void createInterTree(SgFile*, std::vector<SpfInterval*>&, bool, std::vector<Messages>&);
void assignCallsToFile(const std::string&, std::vector<SpfInterval*>&);
void removeNodes(int, std::vector<SpfInterval*>&, std::vector<std::string>&);
void insertIntervals(SgFile*, const std::vector<SpfInterval*>&);
void createMapOfinterval(std::map<int, SpfInterval*> &mapIntervals, const std::vector<SpfInterval*> &intervals);
void initTimeForIntervalTree(const int numOfTopologies, std::vector<SpfInterval*> &intervals);
void aggregatePredictedTimes(std::vector<SpfInterval*> &itervals);
SpfInterval* getMainInterval(SgProject *project, const std::map<std::string, std::vector<SpfInterval*>> &intervals, std::map<std::string, std::vector<Messages>>& SPF_messages);
void uniteIntervalsBetweenProcCalls(std::map<std::string, std::vector<SpfInterval*>> &intervals, const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo);
SpfInterval* findNearestUp(const std::map<SgStatement*, SpfInterval*> &intervals, SgStatement *st);
SpfInterval* findNearestDown(const std::map<SgStatement*, SpfInterval*> &intervals, SgStatement *st);

View File

@@ -0,0 +1,92 @@
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <assert.h>
#include "../Distribution/DvmhDirective.h"
#include "../GraphLoop/graph_loops.h"
#include "directive_analyzer.h"
#include "../Utils/utils.h"
using std::vector;
using std::map;
static void recUniteAcrossOut(LoopGraph *currLoop)
{
if (currLoop->perfectLoop > 1)
{
recUniteAcrossOut(currLoop->children[0]);
if (currLoop->directive)
currLoop->acrossOutAttribute.insert(currLoop->children[0]->acrossOutAttribute.begin(), currLoop->children[0]->acrossOutAttribute.end());
}
}
static void recUnite(vector<LoopGraph*> &loopGraph)
{
for (int i = 0; i < loopGraph.size(); ++i)
{
LoopGraph &currLoop = *loopGraph[i];
if (currLoop.perfectLoop > 1)
{
vector<ParallelDirective*> united;
vector<ParallelDirective*> elems;
LoopGraph *elem = loopGraph[i];
for (int k = 0; k < currLoop.perfectLoop; ++k)
{
elems.push_back(elem->directive);
if (k != currLoop.perfectLoop - 1)
elem = elem->children[0];
}
united.push_back(elems.back());
for (int k = currLoop.perfectLoop - 2; k >= 0; --k)
{
ParallelDirective *first = elems[k];
ParallelDirective *second = united.back();
ParallelDirective *newDir = NULL;
if (first != NULL && second != NULL)
newDir = *first + *second;
else if (first != NULL)
newDir = new ParallelDirective(*first);
else if (first == NULL && second != NULL)
{
newDir = new ParallelDirective(*second);
newDir->parallel.insert(newDir->parallel.begin(), "*");
}
united.push_back(newDir);
}
elem = loopGraph[i];
for (int k = 0; k < currLoop.perfectLoop - 1; ++k)
{
if (elem->directive)
delete elem->directive;
elem->directive = united[currLoop.perfectLoop - k - 1];
elem = elem->children[0];
}
recUniteAcrossOut(loopGraph[i]);
}
else
recUnite(currLoop.children);
}
}
void UniteNestedDirectives(vector<LoopGraph*> &loopGraph)
{
recUnite(loopGraph);
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include <vector>
#include "../GraphLoop/graph_loops.h"
void UniteNestedDirectives(std::vector<LoopGraph*> &loopGraph);

View File

@@ -0,0 +1,490 @@
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <assert.h>
#include "dvm.h"
#include "../ParallelizationRegions/ParRegions_func.h"
#include "../Distribution/GraphCSR.h"
#include "../Distribution/Arrays.h"
#include "../Distribution/Distribution.h"
#include "../Distribution/DvmhDirective_func.h"
#include "../Utils/errors.h"
#include "../LoopAnalyzer/loop_analyzer.h"
#include "directive_parser.h"
#include "directive_creator.h"
#include "../Utils/SgUtils.h"
#include "../Sapfor.h"
#include "../GraphLoop/graph_loops_func.h"
#include "../Transformations/loop_transform.h"
#include "../ExpressionTransform/expr_transform.h"
#include "../GraphCall/graph_calls_func.h"
#include "../Utils/AstWrapper.h"
#define PRINT_DIR_RESULT 0
#define FIRST(x) get<0>(x)
#define SECOND(x) get<1>(x)
#define THIRD(x) get<2>(x)
using std::vector;
using std::pair;
using std::tuple;
using std::map;
using std::set;
using std::make_pair;
using std::make_tuple;
using std::get;
using std::string;
using std::wstring;
extern int sharedMemoryParallelization;
static vector<pair<string, vector<Expression*>>>
groupRealignsDirs(const vector<pair<string, vector<Expression*>>>& toRealign)
{
map<pair<string, string>, vector<vector<Expression*>>> groupedRules;
for (auto& rule : toRealign)
{
auto currRule = rule.second;
string tRule = string(currRule[2]->unparse());
string arrRule = string(currRule[1]->unparse());
groupedRules[make_pair(tRule, arrRule)].push_back(currRule);
}
map<pair<string, string>, vector<Expression*>> mergedGroupedRules;
for (auto& rule : groupedRules)
{
SgExprListExp* mergedList = new SgExprListExp();
for (int z = 0; z < rule.second.size(); ++z)
{
if (z == 0)
mergedList->setLhs(rule.second[z][0]->GetOriginal());
else
mergedList->append(*rule.second[z][0]->GetOriginal());
}
vector<Expression*> medged = rule.second[0];
medged[0] = new Expression(mergedList);
mergedGroupedRules[rule.first] = medged;
}
vector<pair<string, vector<Expression*>>> retVal;
for (auto& elem : mergedGroupedRules)
retVal.push_back(make_pair("", elem.second));
return retVal;
}
//create realigns instead of full template redistribution
pair<vector<Directive*>, vector<Directive*>>
createRealignRules(Statement* st, const uint64_t regId, File *file, const string &templClone,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls, const set<DIST::Array*>& usedArrays,
const pair<int, int> linesBeforeAfter)
{
vector<vector<pair<string, vector<Expression*>>>> optimizedRules(2);
for (int num = 0; num < 2; ++num)
{
for (auto &elemPair : sortArraysByName(usedArrays))
{
DIST::Array* elem = elemPair.second;
if (elem->IsNotDistribute())
continue;
auto realRef = getRealArrayRef(elem, regId, arrayLinksByFuncCalls);
auto rules = realRef->GetAlignRulesWithTemplate(regId);
auto links = realRef->GetLinksWithTemplate(regId);
const auto &templ = realRef->GetTemplateArray(regId);
if (templ == NULL)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
vector<Expression*> realign = { NULL, NULL, NULL, NULL, NULL };
SgVarRefExp *ref = new SgVarRefExp((SgSymbol*)elem->GetNameInLocationS(st));
realign[0] = new Expression(ref);
SgExprListExp *list = new SgExprListExp();
string base = "iEX";
for (int z = 0; z < elem->GetDimSize(); ++z)
{
if (z == 0)
list->setLhs(*new SgVarRefExp(findSymbolOrCreate(file, base + std::to_string(z))));
else
list->append(*new SgVarRefExp(findSymbolOrCreate(file, base + std::to_string(z))));
}
realign[1] = new Expression(list);
if (num == 0)
realign[2] = new Expression(new SgArrayRefExp(*findSymbolOrCreate(file, templClone, new SgArrayType(*SgTypeInt()))));
else
realign[2] = new Expression(new SgArrayRefExp(*findSymbolOrCreate(file, templ->GetShortName(), new SgArrayType(*SgTypeInt()))));
vector<SgExpression*> templateRuleEx(templ->GetDimSize());
std::fill(templateRuleEx.begin(), templateRuleEx.end(), (SgExpression*)NULL);
for (int z = 0; z < elem->GetDimSize(); ++z)
{
if (links[z] != -1)
{
SgExpression *toSet = NULL;
auto symb = new SgVarRefExp(*findSymbolOrCreate(file, base + std::to_string(z)));
if (rules[z] == make_pair(1, 0))
toSet = symb;
else if (rules[z].second == 0)
toSet = &(*new SgValueExp(rules[z].first) * *symb);
else if (rules[z].first == 1)
toSet = &(*symb + *new SgValueExp(rules[z].second));
else
toSet = &(*new SgValueExp(rules[z].first) * *symb + *new SgValueExp(rules[z].second));
templateRuleEx[links[z]] = toSet;
}
}
for (int z = 0; z < templateRuleEx.size(); ++z)
{
SgExpression *toSet = NULL;
if (templateRuleEx[z] == NULL)
toSet = new SgVarRefExp(*findSymbolOrCreate(file, "*"));
else
toSet = templateRuleEx[z];
((SgArrayRefExp*)realign[2]->GetOriginal())->addSubscript(*toSet);
}
optimizedRules[num].push_back(make_pair("", realign));
}
}
vector<vector<pair<string, vector<Expression*>>>> groupedOptRules(2);
groupedOptRules[0] = groupRealignsDirs(optimizedRules[0]);
groupedOptRules[1] = groupRealignsDirs(optimizedRules[1]);
pair<vector<Directive*>, vector<Directive*>> retVal;
for (auto& elem : groupedOptRules[0])
retVal.first.push_back(new CreatedDirective(elem.first, elem.second, linesBeforeAfter.first));
for (auto& elem : groupedOptRules[1])
retVal.second.push_back(new CreatedDirective(elem.first, elem.second, linesBeforeAfter.second));
return retVal;
}
static bool hasFunctionCall(SgExpression* ex)
{
bool ret = false;
if (ex)
{
if (ex->variant() == FUNC_CALL)
return true;
ret |= hasFunctionCall(ex->lhs());
ret |= hasFunctionCall(ex->rhs());
}
return ret;
}
static bool splitToBase(SgExpression *ex, pair<SgExpression*, int> &splited)
{
bool res = true;
if (hasFunctionCall(ex))
return false;
if (ex->variant() == VAR_REF || ex->variant() == ARRAY_REF || ex->variant() == MULT_OP)
splited = make_pair(ex, 0);
else
{
if (ex->variant() == SUBT_OP || ex->variant() == ADD_OP)
{
int minus = (ex->variant() == ADD_OP) ? 1 : -1;
if (ex->rhs())
{
int err, val;
err = CalculateInteger(ex->rhs(), val);
if (err == 0)
{
const int nextEx = ex->lhs()->variant();
if (nextEx == VAR_REF || nextEx == ARRAY_REF || nextEx == MULT_OP)
splited = make_pair(ex->lhs(), minus * val);
else if (nextEx == SUBT_OP || nextEx == ADD_OP)
{
pair<SgExpression*, int> splitedNext;
bool res = splitToBase(ex->lhs(), splitedNext);
if (res == false)
return false;
else
splited = make_pair(splitedNext.first, minus * val + splitedNext.second);
}
else
return false;
}
else
return false;
}
else
return false;
}
else
return false;
}
return res;
}
static void analyzeRightPart(SgExpression *ex, map<DIST::Array*, vector<pair<bool, map<string, pair<int, int>>>>> &rightValues,
const map<DIST::Array*, vector<bool>> &dimsNotMatch)
{
if (ex)
{
if (ex->variant() == ARRAY_REF)
{
const std::string name = ex->symbol()->identifier();
for (auto &elem : dimsNotMatch)
{
if (elem.first->GetShortName() == name)
{
int idx = 0;
for (auto expr = ex->lhs(); expr; expr = expr->rhs(), ++idx)
{
if (elem.second[idx])
{
int err, val;
err = CalculateInteger(expr->lhs(), val);
if (err == 0)
{
if (rightValues[elem.first][idx].first)
{
auto it = rightValues[elem.first][idx].second.find("");
if (it == rightValues[elem.first][idx].second.end())
rightValues[elem.first][idx].second[""] = make_pair(val, val);
else
{
it->second.first = std::min(it->second.first, val);
it->second.second = std::max(it->second.second, val);
}
}
else
{
rightValues[elem.first][idx].first = true;
rightValues[elem.first][idx].second[""] = make_pair(val, val);
}
}
else
{
pair<SgExpression*, int> splited;
bool result = splitToBase(expr->lhs(), splited);
if (result)
{
if (rightValues[elem.first][idx].first)
{
auto key = string(splited.first->unparse());
auto itS = rightValues[elem.first][idx].second.find(key);
if (itS == rightValues[elem.first][idx].second.end())
itS = rightValues[elem.first][idx].second.insert(itS, make_pair(key, make_pair(splited.second, splited.second)));
else
{
itS->second.first = std::min(itS->second.first, splited.second);
itS->second.second = std::max(itS->second.second, splited.second);
}
}
else
{
rightValues[elem.first][idx].first = true;
rightValues[elem.first][idx].second[string(splited.first->unparse())] = make_pair(splited.second, splited.second);
}
}
}
}
}
break;
}
}
}
analyzeRightPart(ex->lhs(), rightValues, dimsNotMatch);
analyzeRightPart(ex->rhs(), rightValues, dimsNotMatch);
}
}
static bool analyzeLeftPart(SgExpression *left, const map<DIST::Array*, vector<bool>>& dimsNotMatch,
map<DIST::Array*, vector<pair<bool, pair<string, int>>>> &leftValues, string &base)
{
const std::string name = left->symbol()->identifier();
for (auto& elem : dimsNotMatch)
{
if (elem.first->GetShortName() == name)
{
int idx = 0;
for (auto ex = left->lhs(); ex; ex = ex->rhs(), ++idx)
{
if (elem.second[idx])
{
int err, val;
err = CalculateInteger(ex->lhs(), val);
if (err == 0)
{
if (leftValues[elem.first][idx].first)
{
if (leftValues[elem.first][idx].second.first != "") // has non zero base expression
return false;
if (leftValues[elem.first][idx].second.second != val) // has conflict writes
return false;
}
else
leftValues[elem.first][idx] = make_pair(true, make_pair("", val));
}
else // WRITE OP can not recognized
{
pair<SgExpression*, int> splited;
bool result = splitToBase(ex->lhs(), splited);
if (result == false)
return false;
if (leftValues[elem.first][idx].first)
{
// has conflict writes
if (leftValues[elem.first][idx].second.first != string(splited.first->unparse()) ||
leftValues[elem.first][idx].second.second != splited.second)
return false;
}
else
{
base = string(splited.first->unparse());
leftValues[elem.first][idx] = make_pair(true, make_pair(base, splited.second));
}
}
}
}
break;
}
}
return true;
}
bool analyzeLoopBody(LoopGraph* loopV,
map<DIST::Array*, vector<pair<bool, pair<string, int>>>>& leftValues,
map<DIST::Array*, vector<pair<bool, map<string, pair<int, int>>>>>& rightValues,
string& base,
const map<DIST::Array*, vector<bool>> &dimsNotMatch,
const map<string, FuncInfo*>& mapFuncInfo)
{
SgStatement* loop = loopV->loop->GetOriginal();
for (auto st = loop; st != loop->lastNodeOfStmt(); st = st->lexNext())
{
if (st->variant() == ASSIGN_STAT)
{
auto left = st->expr(0);
if (left->variant() == ARRAY_REF)
{
bool ok = analyzeLeftPart(left, dimsNotMatch, leftValues, base);
if (ok == false)
return false;
}
analyzeRightPart(st->expr(1), rightValues, dimsNotMatch);
}
else if (st->variant() == PROC_STAT)
{
string name = st->symbol()->identifier();
if (isIntrinsicFunctionName(name.c_str()) == 0)
{
//TODO: contains and modules
auto it = mapFuncInfo.find(name);
int z = 0;
for (SgExpression* ex = st->expr(0); ex; ex = ex->rhs(), ++z)
{
if (ex->lhs()->variant() == ARRAY_REF)
{
bool ok = true;
if (it == mapFuncInfo.end())
ok = analyzeLeftPart(ex->lhs(), dimsNotMatch, leftValues, base);
else
{
if (it->second->funcParams.isArgIn(z) && !it->second->funcParams.isArgOut(z))
analyzeRightPart(ex->lhs(), rightValues, dimsNotMatch);
else
ok = analyzeLeftPart(ex->lhs(), dimsNotMatch, leftValues, base);
}
if (ok == false)
return false;
}
else
analyzeRightPart(ex->lhs(), rightValues, dimsNotMatch);
}
}
}
else
{
for (int i = 0; i < 3; ++i)
analyzeRightPart(st->expr(1), rightValues, dimsNotMatch);
}
}
//is OK ?
return true;
}
void createParallelDirs(File *file,
map<string, vector<Directive*>>& createdDirectives,
vector<Messages>& messages,
const vector<LoopGraph*>& loopsInFile,
const map<string, vector<FuncInfo*>>& allFuncInfo,
const vector<ParallelRegion*>& parallelRegions,
const map<LoopGraph*, void*>& depInfoForLoopGraph,
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
{
const string file_name = file->filename();
map<int, LoopGraph*> mapLoopsInFile;
createMapLoopGraph(loopsInFile, mapLoopsInFile);
map<string, FuncInfo*> mapFuncInfo;
createMapOfFunc(allFuncInfo, mapFuncInfo);
for (int z = 0; z < parallelRegions.size(); ++z)
{
vector<Directive*> toInsert;
const DataDirective& dataDirectives = parallelRegions[z]->GetDataDir();
const vector<int>& currentVariant = parallelRegions[z]->GetCurrentVariant();
DIST::GraphCSR<int, double, attrType>& reducedG = parallelRegions[z]->GetReducedGraphToModify();
DIST::Arrays<int>& allArrays = parallelRegions[z]->GetAllArraysToModify();
auto& tmp = dataDirectives.distrRules;
vector<pair<DIST::Array*, const DistrVariant*>> currentVar;
if (sharedMemoryParallelization == 0)
{
for (int z1 = 0; z1 < currentVariant.size(); ++z1)
currentVar.push_back(make_pair(tmp[z1].first, &tmp[z1].second[currentVariant[z1]]));
}
else
{
for (auto& loop : mapLoopsInFile)
{
auto& rules = loop.second->getDataDir().distrRules;
for (auto& rule : rules)
currentVar.push_back(make_pair(rule.first, &rule.second[0]));
}
}
selectParallelDirectiveForVariant(file, parallelRegions[z], reducedG, allArrays, loopsInFile,
mapLoopsInFile, mapFuncInfo, currentVar,
toInsert, parallelRegions[z]->GetId(), arrayLinksByFuncCalls,
depInfoForLoopGraph, messages);
if (toInsert.size() > 0)
{
auto it = createdDirectives.find(file_name);
if (it == createdDirectives.end())
createdDirectives.insert(it, make_pair(file_name, toInsert));
else
for (int m = 0; m < toInsert.size(); ++m)
it->second.push_back(toInsert[m]);
}
}
}
#undef PRINT_DIR_RESULT
#undef FIRST
#undef SECOND
#undef THIRD

View File

@@ -0,0 +1,63 @@
#pragma once
#include "../Distribution/Distribution.h"
#include "../Utils/errors.h"
#include "../GraphLoop/graph_loops.h"
#include "../Utils/types.h"
void createParallelDirectives(const std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>> &loopInfo,
const std::vector<ParallelRegion*>& regions,
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls,
std::vector<Messages> &messagesForFile);
void selectParallelDirectiveForVariant(File* file,
ParallelRegion* currReg,
DIST::GraphCSR<int, double, attrType>& reducedG,
DIST::Arrays<int>& allArrays,
const std::vector<LoopGraph*>& loopGraph,
const std::map<int, LoopGraph*>& mapLoopGraph,
const std::map<std::string, FuncInfo*>& mapFuncInfo,
const std::vector<std::pair<DIST::Array*, const DistrVariant*>>& distribution,
std::vector<Directive*>& toInsert,
const uint64_t regionId,
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
const std::map<LoopGraph*, void*>& depInfoForLoopGraph,
std::vector<Messages>& messages);
void filterParallelDirectives(const std::map<std::string, std::vector<LoopGraph*>>& loopGraph,
std::map<std::string, std::vector<Directive*>>& createdDirectives);
bool analyzeLoopBody(LoopGraph* loopV,
std::map<DIST::Array*, std::vector<std::pair<bool, std::pair<std::string, int>>>>& leftValues,
std::map<DIST::Array*, std::vector<std::pair<bool, std::map<std::string, std::pair<int, int>>>>>& rightValues,
std::string& base,
const std::map<DIST::Array*, std::vector<bool>>& dimsNotMatch,
const std::map<std::string, FuncInfo*>& mapFuncInfo);
std::pair<std::vector<Directive*>, std::vector<Directive*>> createRealignRules(Statement* spStat, const uint64_t regId, File* file, const std::string& templClone,
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
const std::set<DIST::Array*>& usedArrays,
const std::pair<int, int>);
DIST::Array* getRealArrayRef(DIST::Array* in, const uint64_t regId, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
void shiftAlignRulesForTemplates(const std::set<DIST::Array*>& arrays, const uint64_t regId, DataDirective& dataDirectives, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
void createShadowSpec(const std::map<std::string, std::vector<LoopGraph*>>& loopGraph, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, const std::set<DIST::Array*>& forArrays);
void addShadowFromAnalysis(ParallelDirective* dir, const std::map<DIST::Array*, ArrayInfo*>& currAccesses);
bool checkForConflict(const std::map<DIST::Array*, ArrayInfo*>& currAccesses,
const LoopGraph* currentLoop,
std::map<DIST::Array*, std::pair<int, std::pair<int, int>>, DIST::ArrayComparator>& arrayWriteAcc,
const std::vector<std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>>& acrossInfo,
std::set<DIST::Array*>& acrossOutArrays);
void createParallelDirs(File* file,
std::map<std::string, std::vector<Directive*>>& createdDirectives,
std::vector<Messages>& messages,
const std::vector<LoopGraph*>& loopsInFile,
const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo,
const std::vector<ParallelRegion*>& parallelRegions,
const std::map<LoopGraph*, void*>& depInfoForLoopGraph,
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,536 @@
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include "dvm.h"
#include "directive_omp_parser.h"
#include "directive_parser.h"
#include "../Utils/SgUtils.h"
using std::vector;
using std::map;
using std::set;
using std::string;
void removeOmpDir(SgStatement* st)
{
char* lineS = st->comments();
if (!lineS)
return;
vector<string> split;
splitString(lineS, '\n', split);
int idx = 0;
for (auto& elem : split)
{
string line = elem;
convertToLower(line);
if (line.substr(0, 5) == "!$omp")
lineS[idx + 1] = '_';
else if (line.substr(0, 3) == "!$ ")
lineS[idx + 1] = '_';
idx += line.size() + 1; // with '\n'
}
}
static inline void addToAttribute(SgStatement* st, int var, vector<SgExpression*> list)
{
if (list.size())
{
SgExprListExp* ex = new SgExprListExp();
ex->setLhs(new SgExpression(var, makeExprList(list), NULL));
SgStatement* toAdd = new SgStatement(SPF_ANALYSIS_DIR, NULL, NULL, ex, NULL, NULL);
toAdd->setlineNumber(st->lineNumber());
toAdd->setLocalLineNumber(SPF_OMP_DIR);
//filter
if (var == ACC_PRIVATE_OP)
{
vector<SgExpression*> list_new;
auto attributes = getAttributes<SgStatement*, SgStatement*>(st, set<int>{SPF_ANALYSIS_DIR});
set<string> privates;
for (auto& attr : attributes)
fillPrivatesFromComment(new Statement(attr), privates);
if (privates.size())
{
for (auto& elem : list)
if (privates.find(elem->unparse()) == privates.end())
list_new.push_back(elem);
list = list_new;
if (!list.size())
{
__spf_print(1, "-- skip privates on line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
return;
}
}
}
else if (var == REDUCTION_OP)
{
auto attributes = getAttributes<SgStatement*, SgStatement*>(st, set<int>{SPF_ANALYSIS_DIR});
map<string, set<string>> reduction;
for (auto& attr : attributes)
fillReductionsFromComment(new Statement(attr), reduction);
map<string, set<string>> reductionToAdd;
fillReductionsFromComment(new Statement(toAdd), reductionToAdd);
vector<SgExpression*> list_new;
if (reduction.size())
{
if (reduction == reductionToAdd)
{
__spf_print(1, "-- skip reduction on line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
return;
}
map<string, set<string>> reductionToAddNew;
for (auto& redPair : reductionToAdd)
{
auto it = reduction.find(redPair.first);
if (it == reduction.end())
reductionToAddNew[redPair.first] = redPair.second;
else
{
set<string> newVar;
for (auto& var : redPair.second)
{
auto itVar = it->second.find(var);
if (itVar == it->second.end())
reductionToAddNew[redPair.first].insert(var);
}
}
}
if (!reductionToAddNew.size())
{
__spf_print(1, "-- skip reduction on line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
return;
}
if (reductionToAddNew != reductionToAdd)
{
list.clear();
for (auto& redPair : reductionToAddNew)
for (auto& var : redPair.second)
list.push_back(new SgExpression(ARRAY_OP,
new SgKeywordValExp(redPair.first.c_str()),
new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st)))));
}
}
}
ex = new SgExprListExp();
ex->setLhs(new SgExpression(var, makeExprList(list), NULL));
toAdd = new SgStatement(SPF_ANALYSIS_DIR, NULL, NULL, ex, NULL, NULL);
st->addAttribute(SPF_ANALYSIS_DIR, toAdd, sizeof(SgStatement));
if (var == ACC_PRIVATE_OP)
__spf_print(1, "-- set private attribute to line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
else if (var == REDUCTION_OP)
__spf_print(1, "-- set reduction attribute to line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
}
}
static bool is_write_in_do(SgStatement* st, const string& var)
{
checkNull(st, convertFileName(__FILE__).c_str(), __LINE__);
if (st->variant() != FOR_NODE)
return false;
SgStatement* lastNode = st->lastNodeOfStmt();
for (SgStatement* op = st->lexNext(); st != lastNode; st = st->lexNext())
{
if (st->variant() == ASSIGN_STAT)
{
SgExpression* ex = st->expr(0);
if (ex->variant() == ARRAY_REF || ex->variant() == VAR_REF)
if (var == ex->symbol()->identifier())
return true;
}
else if (st->variant() == FOR_NODE)
{
if (var == isSgForStmt(st)->doName()->identifier())
return true;
}
}
return false;
}
vector<OmpDir> parseOmpInStatement(SgStatement* st, const set<string>& globalPriv, bool forDo)
{
vector<OmpDir> resultAll;
const char* lineS = st->comments();
if (!lineS)
return resultAll;
string comment(lineS);
convertToLower(comment);
vector<string> split;
splitString(comment, '\n', split);
for (int z = split.size() - 1; z >= 0; z--)
{
string line = split[z];
if (line.substr(0, 6) == "!$omp&")
{
if (z - 1 < 0)
break;
split[z - 1] += line.substr(6);
split[z] = "";
}
}
for (auto& line : split)
{
if (line.substr(0, 5) == "!$omp")
{
OmpDir result;
string line1 = "";
int space = 0;
int brake = 0;
for (int z = 0; z < line.size(); ++z)
{
if (brake < 0)
return vector<OmpDir>(); // error
if (brake == 0)
{
if (line[z] == ' ')
space++;
else
space = 0;
if ((line[z] == ' ' && space <= 1) || line[z] != ' ')
line1 += line[z];
}
else
{
if (line[z] != ' ')
line1 += line[z];
}
if (line[z] == '(')
{
while (line1.size() > 2 && line1[line1.size() - 2] == ' ')
line1 = line1.erase(line1.size() - 2, 1);
brake++;
space = 0;
}
else if (line[z] == ')')
brake--;
}
vector<string> lexems;
splitString(line1, ' ', lexems);
bool doLexem = false;
bool end = false;
bool parallel = false;
bool privat = false;
for (auto& lexem : lexems)
{
if (lexem == "do")
{
doLexem = true;
result.keys.insert(lexem);
}
if (lexem == "end")
{
end = true;
result.keys.insert(lexem);
}
if (lexem == "parallel")
{
parallel = true;
result.keys.insert(lexem);
}
if (lexem == "private")
{
privat = true;
result.keys.insert(lexem);
}
}
if (privat == false)
{
if (forDo && doLexem)
{
vector<SgExpression*> list;
for (auto& var : globalPriv)
if (is_write_in_do(st, var))
list.push_back(new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st))));
if (list.size())
addToAttribute(st, ACC_PRIVATE_OP, list);
}
}
for (auto& lexem : lexems)
{
bool priv = lexem.substr(0, strlen("private(")) == "private(";
bool threadpriv = lexem.substr(0, strlen("threadprivate(")) == "threadprivate(";
bool red = lexem.substr(0, strlen("reduction(")) == "reduction(";
if (priv || threadpriv)
{
vector<string> sublex;
splitString(lexem, '(', sublex);
if (sublex.size() == 2 && lexem.back() == ')')
{
splitString(sublex[1].erase(sublex[1].size() - 1), ',', sublex);
vector<SgExpression*> list;
set<string> uniqList;
for (auto& varG : globalPriv)
uniqList.insert(varG);
for (auto& var : sublex)
uniqList.insert(var);
for (auto& var : uniqList)
{
if (priv)
{
result.privVars.insert(var);
list.push_back(new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st))));
}
else
result.threadPrivVars.insert(var);
}
if (forDo && doLexem && priv)
addToAttribute(st, ACC_PRIVATE_OP, list);
}
}
else if (red)
{
vector<string> sublex;
splitString(lexem, '(', sublex);
if (sublex.size() == 2 && lexem.back() == ')')
{
splitString(sublex[1].erase(sublex[1].size() - 1), ':', sublex);
vector<string> vars;
vector<SgExpression*> list;
splitString(sublex[1], ',', vars);
string op = "";
if (sublex[0] == "+")
op = "sum";
else if (sublex[0] == "*")
op = "prod";
else if (sublex[0] == "max")
op = "max";
else if (sublex[0] == "min")
op = "min";
else if (sublex[0] == ".or." || sublex[0] == "or")
op = "or";
else if (sublex[0] == ".and." || sublex[0] == "and")
op = "and";
else if (sublex[0] == ".eqv." || sublex[0] == "eqv")
op = "eqv";
else if (sublex[0] == ".neqv." || sublex[0] == "neqv")
op = "neqv";
if (op != "")
{
for (auto& var : vars)
{
result.redVars[sublex[0]].insert(var);
list.push_back(new SgExpression(ARRAY_OP, new SgKeywordValExp(op.c_str()), new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st)))));
}
}
if (forDo && doLexem && op != "")
addToAttribute(st, REDUCTION_OP, list);
}
}
}
resultAll.push_back(result);
}
}
return resultAll;
}
//TODO: need to use IR and RD for checking
static void filterPrivates(OmpDir& dir)
{
if (dir.privVars.size() == 0)
return;
for (auto st = dir.start; st != dir.end; st = st->lexNext())
{
vector<OmpDir> res;
if (st != dir.start)
{
set<string> dummy;
res = parseOmpInStatement(st, dummy);
}
bool hasParallelDo = false;
for (auto& dir : res)
{
if (dir.keys.find("parallel") != dir.keys.end() ||
dir.keys.find("do") != dir.keys.end())
{
hasParallelDo = true;
}
}
if (res.size() == 0 || !hasParallelDo)
{
if (st->variant() == ASSIGN_STAT)
{
if (st->expr(0))
{
string ref = st->expr(0)->symbol()->identifier();
dir.privVars.erase(ref);
}
}
}
}
}
static vector<OmpDir> findAllGlobalParallelRegions(SgStatement* stFunc)
{
vector<OmpDir> sections;
SgStatement* lastNode = stFunc->lastNodeOfStmt();
for (auto st = stFunc; st != lastNode; st = st->lexNext())
{
if (st == NULL)
{
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
break;
}
if (st->variant() == CONTAINS_STMT)
break;
set<string> dummy;
auto res = parseOmpInStatement(st, dummy);
for (auto& dir : res)
{
auto end = dir.keys.end();
if (dir.keys.find("parallel") != end
&& dir.keys.find("do") == end
&& dir.keys.find("end") == end)
{
if (sections.size() && sections.back().end == NULL) // has open parallel region
{
__spf_print(1, "wrong omp directives placed on line %d\n", st->lineNumber());
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
sections.push_back(dir);
sections.back().start = st;
}
else if (dir.keys.find("parallel") != end
&& dir.keys.find("do") == end
&& dir.keys.find("end") != end)
{
if (!sections.size())
{
__spf_print(1, "wrong omp directives placed on line %d\n", st->lineNumber());
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
sections.back().end = st;
}
}
}
for (auto& dir : sections)
filterPrivates(dir);
return sections;
}
static set<string> getGlobalPrivate(SgStatement* st, const vector<OmpDir>& globalParallelRegions)
{
set<string> globalPrivates;
const int line = st->lineNumber();
if (line > 0)
{
for (auto& reg : globalParallelRegions)
{
if (reg.start->lineNumber() <= line && line < reg.end->lineNumber())
{
if (reg.privVars.size())
return reg.privVars;
else
return globalPrivates;
}
}
}
else
{
for (auto& reg : globalParallelRegions)
{
for (auto stF = reg.start; stF != reg.end; stF = stF->lexNext())
{
if (st == stF)
{
if (reg.privVars.size())
return reg.privVars;
else
return globalPrivates;
}
}
}
}
return globalPrivates;
}
void parseOmpDirectives(SgFile* file, vector<Messages>& currMessages)
{
int funcNum = file->numberOfFunctions();
for (int i = 0; i < funcNum; ++i)
{
SgStatement* st = file->functions(i);
SgStatement* lastNode = st->lastNodeOfStmt();
vector<OmpDir> globalParallelRegions = findAllGlobalParallelRegions(st);
while (st != lastNode)
{
if (st == NULL)
{
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
break;
}
if (st->variant() == CONTAINS_STMT)
break;
if (st->variant() == FOR_NODE)
{
SgForStmt* currSt = (SgForStmt*)st;
if (currSt->isEnddoLoop() == 0)
{
__spf_print(1, "wrong omp directives placed\n");
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
else
parseOmpInStatement(st, getGlobalPrivate(st, globalParallelRegions), true);
}
st = st->lexNext();
}
}
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include <string>
#include <set>
#include <map>
#include <vector>
#include "../Utils/errors.h"
#define SPF_USER_DIR 777
#define SPF_USER_DIR_COPY 999
#define SPF_OMP_DIR 888
struct OmpDir
{
std::set<std::string> privVars;
std::set<std::string> threadPrivVars;
std::map<std::string, std::set<std::string>> redVars;
std::set<std::string> keys;
SgStatement* start = NULL;
SgStatement* end = NULL;
};
void removeOmpDir(SgStatement* st);
std::vector<OmpDir> parseOmpInStatement(SgStatement* st, const std::set<std::string>& globalPriv, bool forDo = false);
void parseOmpDirectives(SgFile* file, std::vector<Messages>& currMessages);

View File

@@ -0,0 +1,656 @@
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstring>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <locale>
#include <set>
#include <map>
#include <assert.h>
#include "directive_parser.h"
#include "../Utils/SgUtils.h"
#include "../LoopAnalyzer/loop_analyzer.h"
#include "../Utils/AstWrapper.h"
#include "../Utils/errors.h"
using std::string;
using std::vector;
using std::set;
using std::tuple;
using std::map;
using std::make_pair;
using std::pair;
bool isSPF_NoInline(Statement *stIn)
{
if (stIn)
{
SgStatement *st = stIn->GetOriginal();
for (auto &data : getAttributes<SgStatement*, SgStatement*>(st, set<int>{ SPF_TRANSFORM_DIR }))
{
SgExpression *exprList = data->expr(0);
while (exprList)
{
if (exprList->lhs()->variant() == SPF_NOINLINE_OP)
{
//__spf_print(1, "found no inline\n");
return true;
}
exprList = exprList->rhs();
}
}
}
return false;
}
static map<SgSymbol*, Symbol*> dictCreated;
static inline string getSymbol(const string& s) { return s; }
static inline string getSymbol(SgSymbol* s) { return s->identifier(); }
static inline string getData(SgExpression *symb, string*, bool moduleNameAdd = false)
{
SgSymbol* base = symb->symbol();
SgSymbol* symbOr = OriginalSymbol(symb->symbol());
if (symbOr == base)
return symbOr->identifier();
else
{
SgStatement* scope = symbOr->scope();
checkNull(scope, convertFileName(__FILE__).c_str(), __LINE__);
if (scope->variant() != MODULE_STMT)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return string(scope->symbol()->identifier()) + "::" + symbOr->identifier();
}
}
static inline Expression* getData(SgExpression *symb, Expression**, bool moduleNameAdd = false)
{
return new Expression(symb);
}
static inline Symbol* getData(SgExpression *symb, Symbol**, bool moduleNameAdd = false)
{
SgSymbol *symbOr = OriginalSymbol(symb->symbol());
auto it = dictCreated.find(symbOr);
if (it == dictCreated.end())
it = dictCreated.insert(it, make_pair(symbOr, new Symbol(symbOr)));
return it->second;
}
template<typename fillType>
void fillPrivatesFromComment(Statement *stIn, set<fillType> &privates, int type)
{
if (stIn)
{
SgStatement *st = stIn->GetOriginal();
if (st->variant() == SPF_ANALYSIS_DIR)
{
SgExpression *exprList = st->expr(0);
while (exprList)
{
const int var = exprList->lhs()->variant();
if ( ((var == ACC_PRIVATE_OP || var == SPF_PROCESS_PRIVATE_OP) && type == -1) ||
(var == ACC_PRIVATE_OP && var == type) ||
(var == SPF_PROCESS_PRIVATE_OP && var == type) )
{
SgExpression *list = exprList->lhs()->lhs();
while (list)
{
fillType *dummy = NULL;
privates.insert(getData(list->lhs(), dummy));
list = list->rhs();
}
break;
}
exprList = exprList->rhs();
}
}
}
}
template void fillPrivatesFromComment(Statement *st, set<string> &privates, int type);
template void fillPrivatesFromComment(Statement *st, set<Symbol*> &privates, int type);
//XXX: need to remove message and to add implementation
extern map<string, vector<Messages>> SPF_messages;
//for simple reduction
template<typename fillType>
void fillReductionsFromComment(Statement *stIn, map<string, set<fillType>> &reduction, bool moduleNameAdd, int type)
{
bool error = false;
if (stIn)
{
SgStatement *st = stIn->GetOriginal();
if (st->variant() == type)
{
SgExpression* exprList = NULL;
if (type == SPF_ANALYSIS_DIR)
exprList = st->expr(0);
else if (type == DVM_PARALLEL_ON_DIR)
exprList = st->expr(1);
while (exprList)
{
if (exprList->lhs()->variant() == REDUCTION_OP)
{
SgExpression *list = exprList->lhs()->lhs();
while (list)
{
SgExpression *currRed = list->lhs(); // with variant ARRAY_OP
fillType redSymb, *dummy = NULL;
//minloc/maxloc
if (currRed->rhs()->variant() == EXPR_LIST)
redSymb = getData(currRed->rhs()->lhs(), dummy, moduleNameAdd);
else
{
redSymb = getData(currRed->rhs(), dummy, moduleNameAdd);
if (currRed->rhs()->variant() == ARRAY_REF)
{
SgExpression* ref = currRed->rhs();
if (ref->lhs() != NULL || ref->rhs() != NULL)
{
//XXX
std::wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Reduction by element of array '%s' is not supported", to_wstring(getSymbol(redSymb)).c_str());
__spf_printToLongBuf(messageR, R182, to_wstring(getSymbol(redSymb)).c_str());
SPF_messages[current_file->filename()].push_back(Messages(ERROR, stIn->lineNumber(), messageR, messageE, 1059));
error = true;
}
}
}
string oper = ((SgKeywordValExp *)(currRed->lhs()))->value();
auto it = reduction.find(oper);
if (oper == "minloc" || oper == "maxloc")
{
//skip
//__spf_print(1, " MAXLOC/MINLOC operation from SPF not supported yet, ignored\n");
}
else
{
if (it == reduction.end())
it = reduction.insert(it, make_pair(oper, set<fillType>()));
it->second.insert(redSymb);
}
list = list->rhs();
}
}
exprList = exprList->rhs();
}
}
}
if (error)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
template void fillReductionsFromComment(Statement *st, map<string, set<string>> &reduction, bool, int);
template void fillReductionsFromComment(Statement *st, map<string, set<Symbol*>> &reduction, bool, int);
//for min/max loc reduction
template<typename fillType>
void fillReductionsFromComment(Statement *stIn, map<string, set<tuple<fillType, fillType, int>>> &reduction, bool moduleNameAdd, int type)
{
if (stIn)
{
SgStatement *st = stIn->GetOriginal();
if (st->variant() == type)
{
SgExpression* exprList = NULL;
if (type == SPF_ANALYSIS_DIR)
exprList = st->expr(0);
else if (type == DVM_PARALLEL_ON_DIR)
exprList = st->expr(1);
while (exprList)
{
if (exprList->lhs()->variant() == REDUCTION_OP)
{
SgExpression *list = exprList->lhs()->lhs();
while (list)
{
SgExpression *currRed = list->lhs();
fillType redSymb, *dummy = NULL;
//minloc/maxloc
if (currRed->rhs()->variant() == EXPR_LIST)
redSymb = getData(currRed->rhs()->lhs(), dummy, moduleNameAdd);
else
redSymb = getData(currRed->rhs(), dummy, moduleNameAdd);
string oper = ((SgKeywordValExp *)(currRed->lhs()))->value();
auto it = reduction.find(oper);
if (oper == "minloc" || oper == "maxloc")
{
fillType arraySymb = getData(currRed->rhs()->rhs()->lhs(), dummy);
int dim = currRed->rhs()->rhs()->rhs()->lhs()->valueInteger();
if (it == reduction.end())
it = reduction.insert(it, make_pair(oper, set<tuple<fillType, fillType, int>>()));
it->second.insert(std::make_tuple(redSymb, arraySymb, dim));
}
else
{
//skip
}
list = list->rhs();
}
}
exprList = exprList->rhs();
}
}
}
}
template void fillReductionsFromComment(Statement *st, map<string, set<tuple<string, string, int>>> &reduction, bool, int);
template void fillReductionsFromComment(Statement *st, map<string, set<tuple<Symbol*, Symbol*, int>>> &reduction, bool, int);
void fillParameterFromComment(Statement *stIn, vector<pair<Expression*, Expression*>> &assigns)
{
if (stIn)
{
SgStatement *st = stIn->GetOriginal();
if (st->variant() == SPF_ANALYSIS_DIR)
{
SgExpression *exprList = st->expr(0);
while (exprList)
{
if (exprList->lhs() && exprList->lhs()->variant() == SPF_PARAMETER_OP)
{
auto paramList = exprList->lhs()->lhs();
while (paramList)
{
assigns.push_back(make_pair(new Expression(paramList->lhs()->lhs()), new Expression(paramList->lhs()->rhs())));
paramList = paramList->rhs();
}
}
exprList = exprList->rhs();
}
}
}
}
template<typename fillType>
static void fillShadowAcross(const int type, Statement *stIn, vector<pair<pair<fillType, string>, vector<pair<int, int>>>> &data, set<fillType> *corner = NULL)
{
if (stIn)
{
SgStatement *st = stIn->GetOriginal();
for (int list = 0; list < 3; ++list)
{
SgExpression *exprList = st->expr(list);
while (exprList)
{
if (exprList->lhs()->variant() == type)
{
SgExpression *listExp = exprList->lhs()->lhs();
while (listExp)
{
SgExpression *list = listExp;
bool needCornerAdd = false;
if (list->lhs()->variant() == ARRAY_OP)
{
list = list->lhs();
needCornerAdd = true;
}
SgSymbol *symb = OriginalSymbol(list->lhs()->symbol());
fillType arrayName, *dummy = NULL;
arrayName = getData(list->lhs(), dummy);
bool cond = false;
if (corner && needCornerAdd)
corner->insert(arrayName);
pair<pair<fillType, string>, vector<pair<int, int>>> *toAdd;
for (int i = 0; i < data.size(); ++i)
{
if (data[i].first.first == arrayName)
{
toAdd = &data[i];
cond = true;
break;
}
}
if (!cond)
{
auto uniqKey = getFromUniqTable(symb);
data.push_back(make_pair(make_pair(arrayName, getShortName(uniqKey)), vector<pair<int, int>>()));
toAdd = &data.back();
}
SgExpression *listEx = list->lhs()->lhs();
int idx = 0;
while (listEx)
{
SgExpression *width = listEx->lhs();
const int left = width->lhs()->valueInteger();
const int right = width->rhs()->valueInteger();
if (toAdd->second.size() <= idx)
toAdd->second.push_back(make_pair(left, right));
else
{
toAdd->second[idx].first = std::max(toAdd->second[idx].first, left);
toAdd->second[idx].second = std::max(toAdd->second[idx].second, right);
}
idx++;
listEx = listEx->rhs();
}
listExp = listExp->rhs();
}
}
exprList = exprList->rhs();
}
}
}
}
template<typename fillType>
void fillShadowAcrossFromComment(const int type, Statement *stIn, vector<pair<pair<fillType, string>, vector<pair<int, int>>>> &data)
{
if (stIn)
if (stIn->GetOriginal()->variant() == SPF_PARALLEL_DIR)
fillShadowAcross(type, stIn, data);
}
template void fillShadowAcrossFromComment(const int type, Statement *st, vector<pair<pair<string, string>, vector<pair<int, int>>>> &data);
template void fillShadowAcrossFromComment(const int type, Statement *st, vector<pair<pair<Symbol*, string>, vector<pair<int, int>>>> &data);
template<typename fillType>
void fillShadowAcrossFromParallel(const int type, Statement *stIn, vector<pair<pair<fillType, string>, vector<pair<int, int>>>> &data, set<fillType> &corner)
{
if (stIn)
if (stIn->GetOriginal()->variant() == DVM_PARALLEL_ON_DIR)
fillShadowAcross(type, stIn, data, &corner);
}
template void fillShadowAcrossFromParallel(const int type, Statement *st, vector<pair<pair<string, string>, vector<pair<int, int>>>> &data, set<string> &corner);
template void fillShadowAcrossFromParallel(const int type, Statement* st, vector<pair<pair<Symbol*, string>, vector<pair<int, int>>>>& data, set<Symbol*> &corner);
template<typename fillType>
void fillRemoteFromComment(Statement *stIn, map<pair<fillType, string>, Expression*> &remote, bool isFull, int type)
{
if (stIn)
{
SgStatement *st = stIn->GetOriginal();
if (st->variant() == type)
{
SgExpression *exprList = NULL;
if (type == SPF_PARALLEL_DIR || type == DVM_REMOTE_ACCESS_DIR)
exprList = st->expr(0);
else if (type == DVM_PARALLEL_ON_DIR)
exprList = st->expr(1);
while (exprList)
{
if (exprList->lhs()->variant() == REMOTE_ACCESS_OP || type == DVM_REMOTE_ACCESS_DIR)
{
SgExpression *list;
if (type == DVM_REMOTE_ACCESS_DIR)
list = exprList;
else
list = exprList->lhs()->lhs();
while (list)
{
fillType arrayName, *dummy = NULL;
arrayName = getData(list->lhs(), dummy);
char *str;
if (list->lhs()->lhs())
str = list->lhs()->lhs()->unparse();
else
str = "";
if (isFull)
remote.insert(make_pair(make_pair(arrayName, string(str)), new Expression(list->lhs())));
else
{
if (list->lhs()->lhs())
remote.insert(make_pair(make_pair(arrayName, string(str)), new Expression(list->lhs()->lhs())));
else
remote.insert(make_pair(make_pair(arrayName, string(str)), new Expression(new SgExprListExp())));
}
list = list->rhs();
}
}
if (type == DVM_REMOTE_ACCESS_DIR)
break;
exprList = exprList->rhs();
}
}
}
}
template void fillRemoteFromComment(Statement *st, map<pair<string, string>, Expression*> &remote, bool isFull, int type);
template void fillRemoteFromComment(Statement *st, map<pair<Symbol*, string>, Expression*> &remote, bool isFull, int type);
template void fillRemoteFromComment(Statement *st, map<pair<Expression*, string>, Expression*> &remote, bool isFull, int type);
void fillAcrossInfoFromDirectives(const LoopGraph *loopInfo, vector<pair<pair<string, string>, vector<pair<int, int>>>> &acrossInfo)
{
SgForStmt *currentLoop = (SgForStmt*)loopInfo->loop;
for (auto &data : getAttributes<SgStatement*, SgStatement*>(currentLoop, set<int>{ SPF_ANALYSIS_DIR, SPF_PARALLEL_DIR, SPF_TRANSFORM_DIR }))
fillShadowAcrossFromComment(ACROSS_OP, new Statement(data), acrossInfo);
}
void fillFissionPrivatesExpansionFromComment(Statement *stIn, vector<string> &vars)
{
if (stIn)
{
SgStatement *st = stIn->GetOriginal();
if (st->variant() == SPF_TRANSFORM_DIR)
{
SgExpression *exprList = st->expr(0);
while (exprList)
{
if (exprList->lhs() && (exprList->lhs()->variant() == SPF_FISSION_OP || exprList->lhs()->variant() == SPF_EXPAND_OP))
{
SgExpression *list = exprList->lhs()->lhs();
while (list)
{
if (list->lhs()->variant() == VAR_REF)
vars.push_back(list->lhs()->symbol()->identifier());
list = list->rhs();
}
}
exprList = exprList->rhs();
}
}
}
}
template<typename fillType>
void fillShrinkFromComment(Statement *stIn, vector<pair<fillType, vector<int>>> &varDims)
{
if (stIn)
{
SgStatement *st = stIn->GetOriginal();
if (st->variant() == SPF_TRANSFORM_DIR)
{
SgExpression *exprList = st->expr(0);
while (exprList)
{
if (exprList->lhs() && (exprList->lhs()->variant() == SPF_SHRINK_OP))
{
SgExpression *list = exprList->lhs()->lhs();
while (list)
{
// get identifier
fillType var, *dummy = NULL;
var = getData(list->lhs(), dummy);
vector<int> dims;
SgExpression *dimList = list->lhs()->lhs();
while (dimList)
{
// filling dimensions
dimList->lhs()->isInteger() ? dims.push_back(dimList->lhs()->valueInteger()) : dims.push_back(-1);
dimList = dimList->rhs();
}
varDims.push_back(make_pair(var, dims));
list = list->rhs();
}
}
exprList = exprList->rhs();
}
}
}
}
template void fillShrinkFromComment(Statement *stIn, vector<pair<Symbol*, vector<int>>> &varDims);
template void fillShrinkFromComment(Statement *stIn, vector<pair<string, vector<int>>> &varDims);
template<typename fillType>
void fillCheckpointFromComment(Statement *stIn, map<int, Expression*> &clauses, set<fillType> &vars, set<fillType> &expt)
{
if (stIn)
{
SgStatement *st = stIn->GetOriginal();
if (st->variant() == SPF_CHECKPOINT_DIR)
{
SgExpression *exprList= st->expr(0);
while (exprList)
{
if (exprList->lhs())
{
SgExpression *toInsert = NULL;
if (exprList->lhs()->variant() == SPF_INTERVAL_OP)
toInsert = new SgExpression(EXPR_LIST, exprList->lhs(), NULL);
else if (exprList->lhs()->variant() == SPF_FILES_COUNT_OP)
toInsert = new SgExpression(EXPR_LIST, exprList->lhs()->lhs(), NULL);
else
toInsert = exprList->lhs()->lhs();
auto it = clauses.find(exprList->lhs()->variant());
if (it == clauses.end())
it = clauses.insert(it, make_pair(exprList->lhs()->variant(), new Expression(toInsert)));
else
{
auto expr = it->second->GetOriginal();
while (expr && expr->rhs())
expr = expr->rhs();
expr->setRhs(toInsert);
}
if (exprList->lhs()->variant() == SPF_VARLIST_OP ||
exprList->lhs()->variant() == SPF_EXCEPT_OP)
{
auto expr = exprList->lhs()->lhs();
while (expr)
{
// get identifier
fillType var, *dummy = NULL;
var = getData(expr->lhs(), dummy);
if (exprList->lhs()->variant() == SPF_VARLIST_OP)
{
auto it = vars.find(var);
if (it == vars.end())
vars.insert(var);
}
else
{
auto it = expt.find(var);
if (it == expt.end())
expt.insert(var);
}
expr = expr->rhs();
}
}
}
exprList = exprList->rhs();
}
}
}
}
template void fillCheckpointFromComment(Statement *stIn, map<int, Expression*> &clauses, set<Symbol*> &vars, set<Symbol*> &expt);
template void fillCheckpointFromComment(Statement *stIn, map<int, Expression*> &clauses, set<string> &vars, set<string> &expt);
void fillInfoFromDirectives(const LoopGraph *loopInfo, ParallelDirective *directive)
{
SgForStmt *currentLoop = (SgForStmt*)loopInfo->loop;
for (auto &data : getAttributes<SgStatement*, SgStatement*>(currentLoop, set<int>{ SPF_ANALYSIS_DIR, SPF_PARALLEL_DIR, SPF_TRANSFORM_DIR }))
{
Statement *sData = new Statement(data);
fillPrivatesFromComment(sData, directive->privates);
fillReductionsFromComment(sData, directive->reduction, true);
fillReductionsFromComment(sData, directive->reductionLoc, true);
fillShadowAcrossFromComment(SHADOW_OP, sData, directive->shadowRenew);
fillShadowAcrossFromComment(ACROSS_OP, sData, directive->across);
map<pair<Symbol*, string>, Expression*> remotes;
fillRemoteFromComment(sData, remotes);
for (auto& elem : remotes)
{
SgSymbol* symb = OriginalSymbol(elem.first.first->GetOriginal());
auto uniqKey = getFromUniqTable(symb);
directive->remoteAccess[make_pair(make_pair(elem.first.first->GetOriginal()->identifier(), getShortName(uniqKey)), elem.first.second)] = new Expression(elem.second->GetOriginal());
}
}
}
void fillInfoFromDirective(Statement* parallel_on, DvmDirective& directive)
{
Statement* sData = parallel_on;
fillReductionsFromComment(sData, directive.reduction, true, DVM_PARALLEL_ON_DIR);
fillReductionsFromComment(sData, directive.reductionLoc, true, DVM_PARALLEL_ON_DIR);
fillShadowAcrossFromParallel(SHADOW_RENEW_OP, sData, directive.shadowRenew, directive.corners);
fillShadowAcrossFromParallel(ACROSS_OP, sData, directive.across, directive.corners);
//TODO:
/*map<pair<Symbol*, string>, Expression*> remotes;
fillRemoteFromComment(sData, remotes, false, DVM_PARALLEL_ON_DIR);
for (auto& elem : remotes)
{
SgSymbol* symb = OriginalSymbol(elem.first.first->GetOriginal());
auto uniqKey = getFromUniqTable(symb);
directive.remoteAccess[make_pair(make_pair(elem.first.first->GetOriginal()->identifier(), getShortName(uniqKey)), elem.first.second)] = new Expression(elem.second->GetOriginal());
}*/
}
int getCoverPropertyFromComment(Statement* stIn)
{
if (stIn)
{
SgStatement* st = stIn->GetOriginal();
if (st->variant() == SPF_ANALYSIS_DIR)
{
SgExpression* exprList = st->expr(0);
while (exprList)
{
if (exprList->lhs() && exprList->lhs()->variant() == SPF_COVER_OP)
{
auto value = exprList->lhs()->lhs();
if (value->isInteger())
return value->valueInteger();
else
return -1;
}
exprList = exprList->rhs();
}
}
}
return 0;
}

View File

@@ -0,0 +1,55 @@
#pragma once
#include <string>
#include <set>
#include <map>
#include "../Utils/AstWrapper.h"
#include "../GraphLoop/graph_loops.h"
#include "../Distribution/DvmhDirective.h"
struct DvmDirective
{
std::set<Symbol*> corners;
std::vector<std::pair<std::pair<Symbol*, std::string>, std::vector<std::pair<int, int>>>> shadowRenew, across;
std::map<std::pair<std::pair<std::string, std::string>, std::string>, Expression*> remoteAccess;
std::map<std::string, std::set<Symbol*>> reduction;
std::map<std::string, std::set<std::tuple<Symbol*, Symbol*, int>>> reductionLoc;
};
bool isSPF_NoInline(Statement *stPrev);
template<typename fillType>
void fillPrivatesFromComment(Statement *st, std::set<fillType> &privates, int type = -1);
template<typename fillType>
void fillReductionsFromComment(Statement *st, std::map<std::string, std::set<fillType>> &reduction, bool moduleNameAdd = false, int type = SPF_ANALYSIS_DIR);
template<typename fillType>
void fillReductionsFromComment(Statement *st, std::map<std::string, std::set<std::tuple<fillType, fillType, int>>> &reduction, bool moduleNameAdd = false, int type = SPF_ANALYSIS_DIR);
void fillParameterFromComment(Statement *st, std::vector<std::pair<Expression*, Expression*>> &assigns);
template<typename fillType>
void fillShadowAcrossFromComment(const int type, Statement *st, std::vector<std::pair<std::pair<fillType, std::string>, std::vector<std::pair<int, int>>>> &data);
template<typename fillType>
void fillShadowAcrossFromParallel(const int type, Statement *st, std::vector<std::pair<std::pair<fillType, std::string>, std::vector<std::pair<int, int>>>> &data, std::set<fillType> &corner);
template<typename fillType>
void fillRemoteFromComment(Statement *st, std::map<std::pair<fillType, std::string>, Expression*> &remote, bool isFull = false, int type = SPF_PARALLEL_DIR);
void fillAcrossInfoFromDirectives(const LoopGraph *loopInfo, std::vector<std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>> &acrossInfo);
void fillInfoFromDirectives(const LoopGraph *loopInfo, ParallelDirective *directive);
void fillInfoFromDirective(Statement* parallel_on, DvmDirective& directive);
void fillFissionPrivatesExpansionFromComment(Statement *stIn, std::vector<std::string> &vars);
template<typename fillType>
void fillShrinkFromComment(Statement *stIn, std::vector<std::pair<fillType, std::vector<int>>> &varDims);
template<typename fillType>
void fillCheckpointFromComment(Statement *stIn, std::map<int, Expression*> &clauses, std::set<fillType> &vars, std::set<fillType> &expt);
int getCoverPropertyFromComment(Statement* stIn);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
#pragma once
SgStatement* createStatFromExprs(const std::vector<Expression*>& exprs);
void insertLoopTempalteDeclaration(SgFile* file, const DataDirective& dataDir,
const std::vector<std::string>& distrRules, const std::vector<std::vector<dist>>& distrRulesSt,
const DIST::Arrays<int>& allArrays,
const bool extractDir, const uint64_t regionId);
void insertTempalteDeclarationToMainFile(SgFile* file, const DataDirective& dataDir,
const std::map<std::string, std::string>& templateDeclInIncludes,
const std::vector<std::string>& distrRules, const std::vector<std::vector<dist>>& distrRulesSt,
const DIST::Arrays<int>& allArrays,
const bool extractDir, const uint64_t regionId,
const std::set<std::string>& includedToThisFile);
void insertDirectiveToFile(SgFile* file, const char* fin_name, const std::vector<Directive*>& toInsert, const bool extractDir, std::vector<Messages>& messagesForFile);
void insertDistributionToFile(SgFile* file, const char* fin_name, const DataDirective& dataDir,
const std::set<std::string>& distrArrays, const std::vector<std::string>& distrRules,
const std::vector<std::vector<dist>>& distrRulesSt,
const std::vector<std::string>& alignRules,
const std::map<std::string, std::vector<LoopGraph*>>& loopGraph,
const DIST::Arrays<int>& allArrays,
DIST::GraphCSR<int, double, attrType>& reducedG,
std::map<std::string, std::map<int, std::set<std::string>>>& commentsToInclude,
std::map<std::string, std::string>& templateDeclInIncludes,
const bool extractDir, std::vector<Messages>& messagesForFile,
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
const std::map<std::string, FuncInfo*>& funcsInFile,
const uint64_t regionId,
const std::set<std::string>& allFileNames);
void insertShadowSpecToFile(SgFile* file, const char* fin_name, const std::set<std::string>& distrArrays,
DIST::GraphCSR<int, double, attrType>& reducedG,
std::map<std::string, std::map<int, std::set<std::string>>>& commentsToInclude,
const bool extractDir, std::vector<Messages>& messagesForFile,
const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays);
void insertDistributionToFile(const char* origFile, const char* outFile, const std::map<int, std::set<std::string>>& commentsToInclude);
void removeDvmDirectives(SgFile* file, const bool toComment);
void insertDistributeDirsToParallelRegions(const std::vector<ParallelRegionLines>* currLines,
const std::vector<Statement*>& reDistrRulesBefore,
const std::vector<Statement*>& reDistrRulesAfter,
const std::vector<Statement*>& reAlignRules);
void insertTemplateModuleUse(SgFile* file, const std::set<uint64_t>& regNum, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
void removeStatementsFromAllproject(const std::set<int>& variants);
void correctTemplateModuleDeclaration(const std::string& folderName);
void insertParallelDirs(SgFile* file, bool extract,
std::vector<Directive*>& createdDirectives,
std::vector<Messages>& messages,
std::map<std::string, std::string>& templateDeclInIncludes,
std::map<std::string, std::map<int, std::set<std::string>>>& commentsToInclude,
const std::vector<FuncInfo*>& callGraph,
const std::vector<ParallelRegion*>& parallelRegions,
const std::map<std::string, std::vector<LoopGraph*>>& loopGraph,
const std::set<std::string>& allFileNames,
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays,
const std::map<DIST::Array*, std::tuple<int, std::string, std::string>>& tableOfUniqNamesByArray);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
#pragma once
struct RemoteRequest
{
LoopGraph* position;
int dimNum;
REMOTE_TYPE value;
int currLine;
int maxDimSize;
explicit RemoteRequest(LoopGraph* position, int dimNum, REMOTE_TYPE value, int currLine, int maxDimSize) :
position(position), dimNum(dimNum), value(value), currLine(currLine), maxDimSize(maxDimSize)
{ }
};
std::map<std::string, ArrayRefExp*>
createRemoteInParallel(const std::pair<LoopGraph*, const ParallelDirective*> under_dvm_dir,
const DIST::Arrays<int> &allArrays,
const std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>> &loopInfo,
DIST::GraphCSR<int, double, attrType> &reducedG,
const DataDirective &data,
const std::vector<int> &currVar,
std::vector<Messages> &messages,
const uint64_t regionId,
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls,
const std::map<std::string, FuncInfo*>& funcMap);
void addRemoteLink(const LoopGraph* loop, const std::map<std::string, FuncInfo*>& funcMap, ArrayRefExp* expr, std::map<std::string, ArrayRefExp*>& uniqRemotes,
const std::set<std::string>& remotesInParallel, std::set<ArrayRefExp*>& addedRemotes, const std::vector<std::string>& mapToLoop,
std::vector<Messages>& messages, const int line, bool bindToLoopDistribution = true);
ArrayRefExp* createRemoteLink(const LoopGraph* currLoop, const DIST::Array* forArray);
std::vector<RemoteRequest>
checkArrayRefInLoopForRemoteStatus(bool ifUnknownArrayAssignFound,
int sumMatched,
int numOfSubs,
int maxMatched,
int currLine,
DIST::Array* currArray,
std::vector<int>& wasFound,
ArrayRefExp* arrayRef,
std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>>& loopInfo,
const std::vector<int>& matchedToDim,
const std::map<int, LoopGraph*>& sortedLoopGraph,
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
const ParallelRegion* region,
const std::vector<LoopGraph*>& parentLoops);

View File

@@ -0,0 +1,772 @@
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <string>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <assert.h>
#include "../Distribution/Arrays.h"
#include "../GraphCall/graph_calls.h"
#include "../GraphLoop/graph_loops.h"
#include "../ParallelizationRegions/ParRegions.h"
#include "remote_access.h"
using std::vector;
using std::pair;
using std::tuple;
using std::map;
using std::set;
using std::make_pair;
using std::make_tuple;
using std::get;
using std::string;
using std::wstring;
#define DEB 0
static set<string> fillRemotesInParallel(const ParallelDirective* dvm_dir)
{
set<string> remotesInParallel;
for (auto& elem : dvm_dir->remoteAccess)
remotesInParallel.insert(elem.first.first.first + "(" + elem.first.second + ")");
return remotesInParallel;
}
static void createRemoteInParallel(const pair<LoopGraph*, const ParallelDirective*>& under_dvm_dir,
const set<DIST::Array*>& doneInLoops,
const map<string, FuncInfo*>& funcMap,
map<string, ArrayRefExp*>& uniqRemotes, vector<Messages>& messages,
const DataDirective& data, const vector<int>& currVar, const uint64_t regionId,
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
{
const set<DIST::Array*> usedArrays = under_dvm_dir.first->usedArrays;
const set<DIST::Array*> usedArraysWrite = under_dvm_dir.first->usedArraysWrite;
const set<string> remotesInParallel = fillRemotesInParallel(under_dvm_dir.second);
set<ArrayRefExp*> addedRemotes;
for (auto& usedArr : usedArrays)
{
if (doneInLoops.find(usedArr) == doneInLoops.end() && usedArraysWrite.find(usedArr) == usedArraysWrite.end())
{
set<DIST::Array*> realRefs;
getRealArrayRefs(usedArr, usedArr, realRefs, arrayLinksByFuncCalls);
bool isDistr = false;
for (auto& realRef : realRefs)
{
auto templ = realRef->GetTemplateArray(regionId);
for (int z = 0; z < data.distrRules.size(); ++z)
{
if (templ == data.distrRules[z].first)
{
for (auto& elem : data.distrRules[z].second[currVar[z]].distRule)
if (elem == BLOCK)
isDistr = true;
break;
}
}
}
if (isDistr)
{
vector<string> mapToLoop;
for (int z = 0; z < usedArr->GetDimSize(); ++z)
mapToLoop.push_back("");
//TODO: find all array refs
addRemoteLink(under_dvm_dir.first, funcMap, createRemoteLink(under_dvm_dir.first, usedArr), uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, -1, false);
__spf_print(DEB, "CRIP: %d, AFTER MAIN CHECK for arrray '%s'\n", __LINE__, usedArr->GetShortName().c_str());
}
}
}
}
static void createRemoteInParallel(const map<DIST::Array*, vector<ArrayOp>> remoteRegularReadsOfTopLoop,
const pair<LoopGraph*, const ParallelDirective*> under_dvm_dir,
const DIST::Arrays<int>& allArrays,
const map<LoopGraph*, map<DIST::Array*, ArrayInfo*>>& loopInfo,
DIST::GraphCSR<int, double, attrType>& reducedG,
const DataDirective& data,
const vector<int>& currVar,
map<string, ArrayRefExp*>& uniqRemotes,
vector<Messages>& messages,
const uint64_t regionId,
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
set<DIST::Array*>& doneInLoops,
const map<string, FuncInfo*>& funcMap)
{
if (!under_dvm_dir.first || !under_dvm_dir.second)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
__spf_print(DEB, "createRemoteInParallel %d, for loop %d\n", __LINE__, under_dvm_dir.first->lineNum);
set<ArrayRefExp*> addedRemotes;
auto it = loopInfo.find(under_dvm_dir.first);
if (it == loopInfo.end())
{
if (under_dvm_dir.first->perfectLoop > 1)
{
pair<LoopGraph*, const ParallelDirective*> nextDir = under_dvm_dir;
nextDir.first = under_dvm_dir.first->children[0];
createRemoteInParallel(remoteRegularReadsOfTopLoop, nextDir, allArrays, loopInfo, reducedG, data, currVar, uniqRemotes, messages, regionId, arrayLinksByFuncCalls, doneInLoops, funcMap);
}
return;
}
const map<DIST::Array*, ArrayInfo*>& currInfo = it->second;
const ParallelDirective* parDir = under_dvm_dir.second;
DIST::Array* arrayRefOnDir = parDir->arrayRef;
set<DIST::Array*> realRefArrayOnDir;
const set<string> remotesInParallel = fillRemotesInParallel(parDir);
const LoopGraph* currLoop = under_dvm_dir.first;
if (!arrayRefOnDir->IsTemplate())
{
getRealArrayRefs(arrayRefOnDir, arrayRefOnDir, realRefArrayOnDir, arrayLinksByFuncCalls);
if (realRefArrayOnDir.size() != 1)
{
vector<vector<tuple<DIST::Array*, int, pair<int, int>>>> allRules(realRefArrayOnDir.size());
int tmpIdx = 0;
for (auto& array : realRefArrayOnDir)
reducedG.GetAlignRuleWithTemplate(array, allArrays, allRules[tmpIdx++], regionId);
if (!isAllRulesEqual(allRules))
{
__spf_print(1, "not supported yet\n");
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
else
arrayRefOnDir = *(realRefArrayOnDir.begin());
}
else
arrayRefOnDir = *(realRefArrayOnDir.begin());
}
// for all array accesses in loop
for (auto& array : currInfo)
{
DIST::Array* arrayRef = array.first;
if (!arrayRef)
continue;
doneInLoops.insert(arrayRef);
const ArrayInfo* currArrayInfo = array.second;
set<DIST::Array*> realArrayRef;
getRealArrayRefs(arrayRef, arrayRef, realArrayRef, arrayLinksByFuncCalls);
for (auto& elem : realArrayRef)
{
arrayRef = elem;
// fill links between current array and array in parallel dir
vector<int> links;
if (arrayRef != arrayRefOnDir)
links = findLinksBetweenArrays(arrayRef, arrayRefOnDir, regionId);
else
{
links.resize(arrayRef->GetDimSize());
for (int k = 0; k < arrayRef->GetDimSize(); ++k)
links[k] = k;
}
//fill info links with template
auto linksWithTempl = arrayRef->GetLinksWithTemplate(regionId);
auto alignRuleWithTempl = arrayRef->GetAlignRulesWithTemplate(regionId);
const DIST::Array* templArray = arrayRef->GetTemplateArray(regionId);
if (!templArray)
continue; // may be error?
DIST::Array* templRefOnDir = arrayRefOnDir;
if (!templRefOnDir->IsTemplate())
templRefOnDir = templRefOnDir->GetTemplateArray(regionId);
if (templArray != templRefOnDir) // different templates
{
doneInLoops.erase(array.first);
continue;
}
// fill distribute data variant
const DistrVariant* distrVar = NULL;
for (int k = 0; k < data.distrRules.size(); ++k)
{
if (data.distrRules[k].first == templArray)
{
distrVar = &data.distrRules[k].second[currVar[k]];
break;
}
}
if (!distrVar)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
// set new redistribute rule, if exist
const DistrVariant* newDistVar = currLoop->getRedistributeRule(templArray);
if (newDistVar)
distrVar = newDistVar;
set<string> parallelVars;
parallelVars.insert(parDir->parallel.begin(), parDir->parallel.end());
vector<string> mapToLoop;
for (int i = 0; i < links.size(); ++i)
{
if (links[i] != -1 && linksWithTempl[i] != -1)
{
bool isCorrect = false;
const bool isInParallel = parallelVars.find(parDir->on[links[i]].first) != parallelVars.end();
if (distrVar->distRule[linksWithTempl[i]] == BLOCK)
{
if (parDir->on[links[i]].first != "*" && isInParallel)
isCorrect = true;
else
isCorrect = false;
}
if (isCorrect)
mapToLoop.push_back(parDir->on[links[i]].first);
else
mapToLoop.push_back("");
}
else
mapToLoop.push_back("");
}
// main check
for (int i = 0; i < links.size(); ++i)
{
bool needToCheck = false;
if (links[i] != -1 && linksWithTempl[i] != -1)
{
const bool isInParallel = parallelVars.find(parDir->on[links[i]].first) != parallelVars.end();
if (distrVar->distRule[linksWithTempl[i]] == BLOCK)
{
if (parDir->on[links[i]].first != "*" && !isInParallel)
needToCheck = false;
else
needToCheck = true;
}
}
else if (linksWithTempl[i] != -1)
{
// if distributed and used in loop with out link with array on dir
if (distrVar->distRule[linksWithTempl[i]] == BLOCK)
{
// check all unrecognized refs
for (auto& unrec : currArrayInfo->arrayAccessUnrec)
{
if (addedRemotes.find(unrec.first) != addedRemotes.end())
continue;
else if (unrec.second.second[i] == REMOTE_TRUE)
{
addRemoteLink(currLoop, funcMap, unrec.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, unrec.second.first);
__spf_print(DEB, "CRIP: %d, REMOTE_TRUE\n", __LINE__);
}
}
// check all regular refs
for (auto& reg : currArrayInfo->arrayAccess)
{
if (addedRemotes.find(reg.first) != addedRemotes.end())
continue;
if (arrayRef == arrayRefOnDir)
continue;
addRemoteLink(currLoop, funcMap, reg.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, reg.second.first);
__spf_print(DEB, "CRIP: %d, IRREG_REFS\n", __LINE__);
}
continue;
}
}
// check if current dimention is distributed
if (needToCheck)
{
// check unregular acceses
for (auto& unrec : currArrayInfo->arrayAccessUnrec)
{
if (addedRemotes.find(unrec.first) != addedRemotes.end())
continue;
if (unrec.second.second[i] == REMOTE_TRUE)
{
addRemoteLink(currLoop, funcMap, unrec.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, unrec.second.first);
__spf_print(DEB, "CRIP: %d, IRREG_REFS && REMOTE_TRUE\n", __LINE__);
}
}
// and check regular acceses
for (auto& regAccess : currArrayInfo->arrayAccess)
{
if (addedRemotes.find(regAccess.first) != addedRemotes.end())
continue;
if (arrayRef == arrayRefOnDir)
continue;
//if has reads in more than one dim and it dims are dirstributed
int countOfDimAcc = 0;
for (int z = 0; z < linksWithTempl.size(); ++z)
{
bool distributed = false;
if (linksWithTempl[z] != -1)
distributed = (distrVar->distRule[linksWithTempl[z]] == BLOCK);
countOfDimAcc += ((regAccess.second.second[z].coefficients.size() != 0) && distributed) ? 1 : 0;
}
if (countOfDimAcc > 1 ||
countOfDimAcc == 1 && parDir->on[links[i]].first == "*")
{
addRemoteLink(currLoop, funcMap, regAccess.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, regAccess.second.first);
__spf_print(DEB, "CRIP: %d ---\n", __LINE__);
continue;
}
//if has distributed dim but loop maped to *
if (parDir->on[links[i]].first == "*")
{
if (linksWithTempl[i] != -1)
if (distrVar->distRule[linksWithTempl[i]] == BLOCK)
{
addRemoteLink(currLoop, funcMap, regAccess.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, regAccess.second.first);
__spf_print(DEB, "CRIP: %d, NOT MAPPED\n", __LINE__);
continue;
}
}
//if this array has no map rules to current array and this dim is distributed
if (currLoop->directiveForLoop)
{
if (currLoop->directiveForLoop->on[links[i]].first != "*")
{
if (regAccess.second.second[i].coefficients.size() == 0)
{
addRemoteLink(currLoop, funcMap, regAccess.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, regAccess.second.first);
__spf_print(DEB, "CRIP: %d, ----\n", __LINE__);
continue;
}
}
}
// check with loop alignment
auto itRegRemote = remoteRegularReadsOfTopLoop.find(array.first);
if (itRegRemote != remoteRegularReadsOfTopLoop.end())
{
bool wasAdd = false;
for (auto& reads : regAccess.second.second[i].coefficients)
{
const pair<int, int>& currReadAcc = reads.first;
for (auto& ref : itRegRemote->second[i].coefficients)
{
if (ref.first == currReadAcc)
{
addRemoteLink(currLoop, funcMap, regAccess.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, regAccess.second.first);
__spf_print(DEB, "CRIP: %d, MISS\n", __LINE__);
wasAdd = true;
break;
}
}
if (wasAdd)
break;
}
}
}
}
} // main check
}
}
if (currLoop->perfectLoop > 1)
{
pair<LoopGraph*, const ParallelDirective*> nextDir = under_dvm_dir;
nextDir.first = currLoop->children[0];
createRemoteInParallel(remoteRegularReadsOfTopLoop, nextDir, allArrays, loopInfo, reducedG, data, currVar, uniqRemotes, messages, regionId, arrayLinksByFuncCalls, doneInLoops, funcMap);
}
}
map<string, ArrayRefExp*>
createRemoteInParallel(const pair<LoopGraph*, const ParallelDirective*> under_dvm_dir,
const DIST::Arrays<int>& allArrays,
const map<LoopGraph*, map<DIST::Array*, ArrayInfo*>>& loopInfo,
DIST::GraphCSR<int, double, attrType>& reducedG,
const DataDirective& data,
const vector<int>& currVar,
vector<Messages>& messages,
const uint64_t regionId,
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
const map<string, FuncInfo*>& funcMap)
{
map<string, ArrayRefExp*> uniqRemotes;
set<DIST::Array*> doneInLoops;
createRemoteInParallel(under_dvm_dir.first->remoteRegularReads, under_dvm_dir, allArrays, loopInfo, reducedG, data, currVar, uniqRemotes, messages, regionId, arrayLinksByFuncCalls, doneInLoops, funcMap);
createRemoteInParallel(under_dvm_dir, doneInLoops, funcMap, uniqRemotes, messages, data, currVar, regionId, arrayLinksByFuncCalls);
return uniqRemotes;
}
static void addInfoToMap(map<LoopGraph*, map<DIST::Array*, ArrayInfo*>>& loopInfo, LoopGraph* position, DIST::Array* array,
ArrayRefExp* arrayRef, const int dimNum, const REMOTE_TYPE& value, const int currLine,
const int maxDimSize, vector<RemoteRequest>& requests)
{
requests.push_back(RemoteRequest(position, dimNum, value, currLine, maxDimSize));
auto it = loopInfo.find(position);
if (loopInfo.end() == it)
it = loopInfo.insert(it, make_pair(position, map<DIST::Array*, ArrayInfo*>()));
auto it1 = it->second.find(array);
if (it1 == it->second.end())
it1 = it->second.insert(it1, make_pair(array, new ArrayInfo()));
auto it2 = it1->second->arrayAccessUnrec.find(arrayRef);
if (it2 == it1->second->arrayAccessUnrec.end())
{
it2 = it1->second->arrayAccessUnrec.insert(it2, make_pair(arrayRef, make_pair(currLine, vector<REMOTE_TYPE>())));
it2->second.second.resize(maxDimSize);
std::fill(it2->second.second.begin(), it2->second.second.end(), REMOTE_NONE);
}
if (dimNum == -1)
{
for (int z = 0; z < it2->second.second.size(); ++z)
it2->second.second[z] |= value;
}
else
it2->second.second[dimNum] |= value;
if (value == REMOTE_TRUE)
__spf_print(DEB, "RemoteAccess[%d]: true for dim %d and array %s, loop line %d\n", __LINE__, dimNum, array->GetShortName().c_str(), position->lineNum);
}
static pair<DIST::Array*, const DistrVariant*>
getDistrVariant(const vector<pair<DIST::Array*, vector<DistrVariant>>>& distrRules,
DIST::Array* forTempl, const vector<int>& currentVariant)
{
pair<DIST::Array*, const DistrVariant*> currentVar;
for (int z1 = 0; z1 < currentVariant.size(); ++z1)
{
if (distrRules[z1].first == forTempl)
{
currentVar = make_pair(distrRules[z1].first, &distrRules[z1].second[currentVariant[z1]]);
break;
}
}
if (!currentVar.first)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return currentVar;
}
// call this function for each array reference under loop(s)
vector<RemoteRequest>
checkArrayRefInLoopForRemoteStatus(bool ifUnknownArrayAssignFound,
int sumMatched, // sum of matched dimensions of 'arrayRef' to each 'parentLoops'
int numOfSubs, // number of subscriptions of 'arrayRef'
int maxMatched, // maximum numbe of matched dimensions of 'arrayRef' to each 'parentLoops'
int currLine, // current line in source code of 'arrayRef'
DIST::Array* currArray, // DIST::Array of 'arrayRef'
vector<int>& wasFoundForLoop, // size == 'parentLoops'.size(), init value -> 0, each position is sum of match dims count of 'arrayRef'
ArrayRefExp* arrayRef, // current expression of array ref under all 'parentLoops',
map<LoopGraph*, map<DIST::Array*, ArrayInfo*>>& loopInfo,
const vector<int>& matchedToDim, // size == 'parentLoops'.size(), init value -> -1, each position is dimension of match 'arrayRef' for 'parentLoop'
const map<int, LoopGraph*>& sortedLoopGraph,
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
const ParallelRegion* region,
const vector<LoopGraph*>& parentLoops) // all loops which are associated with 'arrayRef'
{
vector<RemoteRequest> requests;
if (sumMatched != parentLoops.size() && sumMatched == numOfSubs)
{
set<DIST::Array*> realArrayRefs;
getRealArrayRefs(currArray, currArray, realArrayRefs, arrayLinksByFuncCalls);
bool ok = true;
DIST::Array* templ = NULL;
vector<int> alignCoefs;
for (auto& real : realArrayRefs)
{
DIST::Array* curr = real->GetTemplateArray(region->GetId(), false);
alignCoefs = real->GetLinksWithTemplate(region->GetId());
if (templ == NULL)
templ = curr;
else if (templ != curr)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
string debOutStr = "";
char buf[256];
sprintf(buf, "RemoteAccess[%d]: check aligns for '%s'\n", __LINE__, currArray->GetShortName().c_str());
debOutStr += buf;
for (int z = 0; z < wasFoundForLoop.size(); ++z)
{
sprintf(buf, "RemoteAccess[%d]: check aligns %d == %d\n", __LINE__, z, wasFoundForLoop[z]);
debOutStr += buf;
}
for (int z = 0; z < matchedToDim.size(); ++z)
{
sprintf(buf, "RemoteAccess[%d]: matchedToDim[%d] = %d\n", __LINE__, z, matchedToDim[z]);
debOutStr += buf;
}
for (int l = 0; l < alignCoefs.size(); ++l)
{
sprintf(buf, "RemoteAccess[%d]: alignCoefs[%d] = %d\n", __LINE__, l, alignCoefs[l]);
debOutStr += buf;
}
//check array's alignment
for (int z = 0; z < wasFoundForLoop.size() && ok; ++z)
{
auto it = sortedLoopGraph.find(parentLoops[z]->lineNum);
if (it == sortedLoopGraph.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (!templ)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const DataDirective& dataDirectives = region->GetDataDir();
const vector<int>& currentVariant = region->GetCurrentVariant();
pair<DIST::Array*, const DistrVariant*> currentVar = getDistrVariant(dataDirectives.distrRules, templ, currentVariant);
LoopGraph* loop = it->second;
if (!loop->directiveForLoop)
{
if (wasFoundForLoop[z])
{
if (matchedToDim[z] != -1 && alignCoefs[matchedToDim[z]] != -1 &&
currentVar.second->distRule[alignCoefs[matchedToDim[z]]] == distType::BLOCK)
{
ok = false;
if (!ok)
{
__spf_print(DEB, "%s\n", debOutStr.c_str());
__spf_print(DEB, "RemoteAccess[%d]: call addInfoMaps from aligns miss\n", __LINE__);
__spf_print(DEB, "RemoteAccess[%d]: z = %d\n", __LINE__, z);
addInfoToMap(loopInfo, parentLoops[z], currArray, arrayRef, matchedToDim[z], REMOTE_TRUE, currLine, numOfSubs, requests);
}
}
}
continue;
}
//apply redistribute
if (loop->getRedistributeRule(currentVar.first) != NULL)
currentVar.second = loop->getRedistributeRule(currentVar.first);
DIST::Array* loopT = loop->directiveForLoop->arrayRef;
sprintf(buf, "RemoteAccess[%d]: z = %d, array '%s'\n", __LINE__, z, loopT->GetShortName().c_str());
debOutStr += buf;
int dimToMap = -1;
for (int z1 = 0; z1 < loopT->GetDimSize(); ++z1)
if (loop->directiveForLoop->on[z1].first != "*")
dimToMap = z1;
sprintf(buf, "RemoteAccess[%d]: z = %d, dimToMap = %d\n", __LINE__, z, dimToMap);
debOutStr += buf;
if (dimToMap != -1)
{
if (loopT != templ && !loopT->IsTemplate())
{
sprintf(buf, "RemoteAccess[%d]: z = %d, false check !=\n", __LINE__, z);
debOutStr += buf;
DIST::Array* loopTempl = loopT->GetTemplateArray(region->GetId(), false);
vector<int> loopAlignCoefs = loopT->GetLinksWithTemplate(region->GetId());
if (loopTempl == NULL)
{
set<DIST::Array*> tmpSet;
getRealArrayRefs(loopT, loopT, tmpSet, arrayLinksByFuncCalls);
set<DIST::Array*> templates;
for (auto& elem : tmpSet)
{
loopTempl = elem->GetTemplateArray(region->GetId(), false);
loopAlignCoefs = elem->GetLinksWithTemplate(region->GetId());
templates.insert(loopTempl);
}
if (templates.size() != 1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
if (loopTempl)
{
sprintf(buf, "RemoteAccess[%d]: z = %d, array '%s'\n", __LINE__, z, loopTempl->GetShortName().c_str());
debOutStr += buf;
}
if (templ != loopTempl)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (loopAlignCoefs.size() == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (loopAlignCoefs.size() <= dimToMap)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (loopAlignCoefs[dimToMap] == -1)
{
//TODO: need more tests for this case: prev bug => bugreport_1676461809
/*if (loop->hasParalleDirectiveBefore())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
else*/
continue;
}
else
dimToMap = loopAlignCoefs[dimToMap];
}
else if (loopT != templ && loopT->IsTemplate())
{
bool isDistr = false;
for (auto& elem : currentVar.second->distRule)
if (elem == BLOCK)
isDistr = true;
if (isDistr)
{
ok = false;
__spf_print(DEB, "%s\n", debOutStr.c_str());
__spf_print(DEB, "RemoteAccess[%d]: call addInfoMaps from template miss\n", __LINE__);
__spf_print(DEB, "RemoteAccess[%d]: z = %d\n", __LINE__, z);
addInfoToMap(loopInfo, parentLoops[z], currArray, arrayRef, matchedToDim[z], REMOTE_TRUE, currLine, numOfSubs, requests);
}
continue;
}
sprintf(buf, "RemoteAccess[%d]: ** z = %d, dimToMap = %d\n", __LINE__, z, dimToMap);
debOutStr += buf;
for (int z = 0; z < currentVar.second->distRule.size(); ++z)
{
sprintf(buf, "RemoteAccess[%d]: distRule[%d] = %d\n", __LINE__, z, currentVar.second->distRule[z]);
debOutStr += buf;
}
if (wasFoundForLoop[z])
{
if (matchedToDim[z] != -1 && currentVar.second->distRule[alignCoefs[matchedToDim[z]]] == distType::BLOCK)
{
bool found = false;
for (int l = 0; l < alignCoefs.size(); ++l)
{
if (alignCoefs[l] == dimToMap)
found = true;
}
ok = found;
if (!ok)
{
__spf_print(DEB, "%s\n", debOutStr.c_str());
__spf_print(DEB, "RemoteAccess[%d]: call addInfoMaps from aligns miss\n", __LINE__);
__spf_print(DEB, "RemoteAccess[%d]: z = %d\n", __LINE__, z);
__spf_print(DEB, "RemoteAccess[%d]: dimToMap = %d\n", __LINE__, dimToMap);
addInfoToMap(loopInfo, parentLoops[z], currArray, arrayRef, matchedToDim[z], REMOTE_TRUE, currLine, numOfSubs, requests);
}
}
}
else
{
bool distrAny = false;
bool distrAll = true;
int dDim = -1;
for (int idx = 0; idx < alignCoefs.size(); ++idx)
{
if (currentVar.second->distRule[idx] == distType::BLOCK)
{
dDim = idx;
distrAny = true;
}
else
distrAll = false;
}
if (matchedToDim[z] == -1 && distrAny && !distrAll)
{
ok = false;
if (!ok)
{
__spf_print(DEB, "%s\n", debOutStr.c_str());
__spf_print(DEB, "RemoteAccess[%d]: call addInfoMaps from aligns miss\n", __LINE__);
__spf_print(DEB, "RemoteAccess[%d]: z = %d\n", __LINE__, z);
__spf_print(DEB, "RemoteAccess[%d]: dimToMap = %d\n", __LINE__, dimToMap);
addInfoToMap(loopInfo, parentLoops[z], currArray, arrayRef, dDim, REMOTE_TRUE, currLine, numOfSubs, requests);
}
}
}
}
}
if (ok && currArray->GetDimSize() > 1)
for (int z = 0; z < wasFoundForLoop.size(); ++z)
wasFoundForLoop[z] = 1;
}
if (ifUnknownArrayAssignFound)
{
if (sumMatched != numOfSubs ||
maxMatched != 1 ||
(sumMatched != parentLoops.size() && sumMatched != numOfSubs))
{
int local = 0;
bool hasLimits = false;
for (int i = 0; i < wasFoundForLoop.size(); ++i)
{
if (wasFoundForLoop[i] == 1)
{
auto itLoop = sortedLoopGraph.find(parentLoops[i]->lineNum);
if (itLoop == sortedLoopGraph.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (itLoop->second->hasLimitsToParallel())
hasLimits = true;
}
}
for (int i = 0; i < wasFoundForLoop.size(); ++i)
{
if (wasFoundForLoop[i] != 1)
{
for (int k = 0; k < numOfSubs; ++k)
{
if (hasLimits)
{
__spf_print(DEB, "RemoteAccess[%d]: call addInfoMaps from hasLimits\n", __LINE__);
addInfoToMap(loopInfo, parentLoops[i], currArray, arrayRef, k, REMOTE_TRUE, currLine, numOfSubs, requests);
}
}
}
}
}
}
return requests;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,150 @@
#pragma once
#include <map>
#include <vector>
#include <string>
#include <set>
struct FuncInfo;
struct LoopGraph;
struct ShadowNode;
struct CommonBlock;
typedef enum node : int { PARALLEL_DIR = 0, FUNCTION_CALL, PROCEDURE_CALL, STOP, START, END } nodeType;
struct ShadowElement
{
std::vector<std::pair<int, int>> bounds;
std::map<FuncInfo*, std::string> origNameByProc;
bool corner;
ShadowElement() { }
ShadowElement(const std::vector<std::pair<int, int>>& bounds,
const std::pair<FuncInfo*, std::string>& origName,
bool corner) : bounds(bounds), corner(corner)
{
origNameByProc[origName.first] = origName.second;
}
bool operator==(const ShadowElement& left) const
{
return bounds == left.bounds && origNameByProc == left.origNameByProc && corner == left.corner;
}
};
struct NextNode
{
ShadowNode* shNode;
std::set<DIST::Array*> writeTo;
bool isBackWard;
bool hasRealigns;
NextNode() { }
NextNode(ShadowNode* shNode, const std::set<DIST::Array*>& writeTo, bool hasRealigns = false)
: shNode(shNode), writeTo(writeTo), isBackWard(false), hasRealigns(hasRealigns)
{ }
bool operator==(const NextNode& left) const
{
return (shNode == left.shNode) && (writeTo == left.writeTo);
}
bool operator<(const NextNode& left) const
{
return shNode < left.shNode;
}
};
struct PrevNode
{
ShadowNode* shNode;
bool* isBackWard;
bool* hasRealigns;
PrevNode() { }
PrevNode(ShadowNode* shNode, bool* isBackWard = NULL, bool* hasRealigns = NULL)
: shNode(shNode), isBackWard(isBackWard), hasRealigns(hasRealigns)
{ }
bool operator==(const PrevNode& left) const
{
return shNode == left.shNode;
}
};
struct ShadowNode
{
void *info;
nodeType type;
//file and line
std::pair<FuncInfo*, int> location;
std::map<DIST::Array*, std::vector<ShadowElement>> shadows;
std::map<DIST::Array*, std::vector<ShadowElement>> newShadows;
std::vector<NextNode> next;
//std::vector<PrevNode> prev;
ShadowNode(void* info, nodeType type, FuncInfo* func, int line) : info(info), type(type), location(std::make_pair(func, line)) { }
void MoveShadow(const std::pair<DIST::Array*, std::vector<ShadowElement>>& shadowAdd)
{
for (auto& elem : shadowAdd.second)
newShadows[shadowAdd.first].push_back(elem);
}
void MergeNewShadowElements()
{
for (auto& elemByArray : newShadows)
{
ShadowElement newElems;
for (int z = 0; z < elemByArray.second.size(); ++z)
{
if (z == 0)
newElems = elemByArray.second[0];
else
{
newElems.corner |= elemByArray.second[z].corner;
for (auto& fElem : elemByArray.second[z].origNameByProc)
newElems.origNameByProc[fElem.first] = fElem.second;
int k = 0;
for (auto& bound : elemByArray.second[z].bounds)
{
newElems.bounds[k].first = std::max(newElems.bounds[k].first, bound.first);
newElems.bounds[k].second = std::max(newElems.bounds[k].second, bound.second);
++k;
}
}
}
if (elemByArray.second.size())
{
elemByArray.second.clear();
elemByArray.second.push_back(newElems);
}
}
}
void addNext(const NextNode& nextNode)
{
bool exist = false;
for (int z = 0; z < next.size() && !exist; ++z)
if (next[z] == nextNode)
exist = true;
if (!exist)
next.push_back(nextNode);
}
};
void GroupShadow(const std::map<std::string, std::vector<FuncInfo*>>& funcs,
const std::map<std::string, std::vector<LoopGraph*>>& loops,
const DIST::Arrays<int>& allArrays,
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
const std::map<std::string, CommonBlock*>& commonBlocks);
void clearAllocatedShadowNodes();
void devourShadowByRemote(void* file, const std::map<std::string, FuncInfo*>& allFuncs, const std::vector<LoopGraph*>& loops, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
void transformShadowIfFull(void* file, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,236 @@
#include "Array.h"
#include "../Utils/errors.h"
#include "../Utils/utils.h"
#include "../GraphCall/graph_calls.h"
using namespace std;
static vector<pair<int, int>> applyNewOrder(const vector<pair<int, int>>& in, const vector<int>& newOrder)
{
int countOfDepr = 0;
for (int z = 0; z < in.size(); ++z)
countOfDepr += (in[z].first == 0 && in[z].second == 0) ? 1 : 0;
if (newOrder.size() == 0)
return in;
if (newOrder.size() + countOfDepr != in.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
vector<pair<int, int>> tmp, retTmp(newOrder.size());
for (int z = 0; z < in.size(); ++z)
if (!(in[z].first == 0 && in[z].second == 0))
tmp.push_back(in[z]);
for (int z = 0; z < newOrder.size(); ++z)
retTmp[z] = tmp[newOrder[z]];
vector<pair<int, int>> retVal;
for (int z = 0, z1 = 0; z < in.size(); ++z)
if ((in[z].first == 0 && in[z].second == 0))
retVal.push_back(in[z]);
else
retVal.push_back(retTmp[z1++]);
return retVal;
}
static vector<int> applyNewOrder(const vector<int> &in, const vector<int> &newOrder)
{
int countOfDepr = 0;
for (int z = 0; z < in.size(); ++z)
countOfDepr += (in[z] == -1) ? 1 : 0;
if (newOrder.size() == 0)
return in;
if (newOrder.size() + countOfDepr != in.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
vector<int> tmp, retTmp(newOrder.size());
for (int z = 0; z < in.size(); ++z)
if (in[z] != -1)
tmp.push_back(in[z]);
for (int z = 0; z < newOrder.size(); ++z)
retTmp[z] = tmp[newOrder[z]];
vector<int> retVal;
for (int z = 0, z1 = 0; z < in.size(); ++z)
if (in[z] == -1)
retVal.push_back(in[z]);
else
retVal.push_back(retTmp[z1++]);
return retVal;
}
template<typename T>
static vector<T> applyNewOrderS(const vector<T> &in, const vector<int> &newOrder)
{
vector<T> retVal(in.size());
if (newOrder.size() == 0)
return in;
if (newOrder.size() != in.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int z = 0; z < newOrder.size(); ++z)
retVal[z] = in[newOrder[z]];
return retVal;
}
namespace Distribution
{
vector<pair<int, int>> TemplateLink::GetAlignRules() const
{
vector<pair<int, int>> retVal = alignRuleWithTemplate;
if (templateArray == NULL)
return retVal;
vector<int> newOrder = templateArray->GetNewTemplateDimsOrder();
if (newOrder.size() == 0)
return alignRuleWithTemplate;
else
return applyNewOrder(retVal, newOrder);
}
vector<int> TemplateLink::GetLinks() const
{
vector<int> retVal = linkWithTemplate;
if (templateArray == NULL)
return retVal;
vector<int> newOrder = templateArray->GetNewTemplateDimsOrder();
if (newOrder.size() == 0)
return linkWithTemplate;
else
return applyNewOrder(retVal, newOrder);
}
string TemplateLink::toString() const
{
string retVal = "";
retVal += "#" + to_string(linkWithTemplate.size());
for (int i = 0; i < linkWithTemplate.size(); ++i)
retVal += "#" + to_string(linkWithTemplate[i]);
retVal += "#" + to_string(alignRuleWithTemplate.size());
for (int i = 0; i < alignRuleWithTemplate.size(); ++i)
retVal += "#" + to_string(alignRuleWithTemplate[i].first) + "#" + to_string(alignRuleWithTemplate[i].second);
retVal += "#" + to_string((long long)templateArray);
return retVal;
}
void TemplateLink::AddRule(const int dimNum, int dimTempl, const pair<int, int>& rule, Array* templateArray_)
{
linkWithTemplate[dimNum] = dimTempl;
alignRuleWithTemplate[dimNum] = rule;
templateArray = templateArray_;
}
const vector<pair<int, int>>& Array::GetSizes()
{
if (templateDimsOrder.size() == 0)
return sizes;
else
{
if (orderedSizes.size() == 0)
orderedSizes = applyNewOrderS(sizes, templateDimsOrder);
return orderedSizes;
}
}
const vector<pair<pair<Expression*, pair<int, int>>, pair<Expression*, pair<int, int>>>>&
Array::GetSizesExpr()
{
if (templateDimsOrder.size() == 0)
return sizesExpr;
else
{
if (orderedSizesExpr.size() == 0)
orderedSizesExpr = applyNewOrderS(sizesExpr, templateDimsOrder);
return orderedSizesExpr;
}
}
void printArrayInfo(const string& file, const map<tuple<int, string, string>, pair<Array*, ArrayAccessInfo*>>& declaredArrays)
{
FILE* out = fopen(file.c_str(), "w");
if (out == NULL)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (auto& elem : declaredArrays)
{
Array* currA = elem.second.first;
ArrayAccessInfo* info = elem.second.second;
fprintf(out, "Array '%s' (full name '%s'):\n", currA->GetShortName().c_str(), currA->GetName().c_str());
auto loc = currA->GetLocation();
string locN = "";
if (loc.first == l_COMMON)
locN = "COMMON ";
else if (loc.first == l_MODULE)
locN = "MODULE ";
else if (loc.first == l_PARAMETER)
locN = "PARAMETER of ";
else if (loc.first == l_LOCAL)
locN = "LOCAL of ";
else if (loc.first == l_LOCAL_SAVE)
locN = "LOCAL (save) of ";
else if (loc.first == l_STRUCT)
locN = "STRUCT ";
else
locN = "UNKN ";
locN += "'" + loc.second + "'";
fprintf(out, " type: %s\n", locN.c_str());
for (auto& byFile : info->GetAllAccessInfo())
{
fprintf(out, " FOR FILE '%s':\n", convertFileName(byFile.first.c_str()).c_str());
for (auto& byLine : byFile.second)
for (auto& onLine : byLine.second)
fprintf(out, " %s\n", onLine.PrintInfo().c_str());
}
fprintf(out, "=============== \n\n");
}
fclose(out);
}
void fixTypeOfArrayInfoWithCallGraph(map<tuple<int, string, string>, pair<Array*, ArrayAccessInfo*>>& declaredArrays,
const map<string, FuncInfo*>& allFuncs)
{
for (auto& elem : declaredArrays)
{
ArrayAccessInfo* info = elem.second.second;
info->checkAndUpdate(allFuncs);
}
}
void ArrayAccessInfo::checkAndUpdate(const map<string, FuncInfo*>& allFuncs)
{
for (auto& byFile : accessPatterns)
{
for (auto& byLine : byFile.second)
{
for (auto& acc : byLine.second)
{
if (acc.underFunctionPar != -1)
{
auto it = allFuncs.find(acc.fName);
if (it != allFuncs.end())
{
if (it->second->funcParams.isArgIn(acc.underFunctionPar) &&
!it->second->funcParams.isArgOut(acc.underFunctionPar))
{
//switch to READ
acc.type = 0;
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,812 @@
#pragma once
#include <string>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <climits>
#include "DvmhDirectiveBase.h"
#include "../Utils/utils.h"
#include "../Utils/errors.h"
class Symbol;
class Expression;
struct FuncInfo;
#define STRING std::string
#define VECTOR std::vector
#define PAIR std::pair
#define MAP std::map
#define SET std::set
#define TO_STR std::to_string
#if __SPF
extern int sharedMemoryParallelization;
#endif
namespace Distribution
{
typedef enum distFlag : int { DISTR = 0, NO_DISTR, SPF_PRIV, IO_PRIV } distFlagType;
typedef enum arrayLocation : int { l_LOCAL = 0, l_COMMON, l_MODULE, l_PARAMETER, l_STRUCT, l_LOCAL_SAVE } arrayLocType;
class Array;
class TemplateLink
{
private:
VECTOR<int> linkWithTemplate;
VECTOR<PAIR<int, int>> alignRuleWithTemplate;
Array *templateArray;
public:
TemplateLink(const int dimSize)
{
linkWithTemplate.resize(dimSize);
alignRuleWithTemplate.resize(dimSize);
for (int i = 0; i < dimSize; ++i)
linkWithTemplate[i] = -1;
templateArray = NULL;
}
TemplateLink(const TemplateLink &copy)
{
linkWithTemplate = copy.linkWithTemplate;
alignRuleWithTemplate = copy.alignRuleWithTemplate;
templateArray = copy.templateArray;
}
Array* GetTemplateArray() const { return templateArray; }
VECTOR<PAIR<int, int>> GetAlignRules() const;
VECTOR<int> GetLinks() const;
void AddRule(const int dimNum, int value, const PAIR<int, int> &rule, Array *templateArray_);
STRING toString() const;
};
class Array
{
private:
unsigned id;
STRING name;
STRING shortName;
int dimSize;
int typeSize; // size of one element of array
// calculated sizes
VECTOR<PAIR<int, int>> sizes;
// original sizes + shifts
VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>> sizesExpr;
VECTOR<PAIR<int, int>> orderedSizes;
VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>> orderedSizesExpr;
// template info by region
MAP<uint64_t, TemplateLink*> templateInfo;
bool isTemplFlag;
bool isLoopArrayFlag;
distFlag isNonDistribute;
Symbol *declSymbol;
STRING uniqKey;
// PAIR<FILE, LINE>
SET<PAIR<STRING, int>> declPlaces;
MAP<PAIR<STRING, int>, Symbol*> declPlacesSymbol;
//file-> map[incFile, line] -> symbol
MAP<STRING, MAP<PAIR<STRING, int>, Symbol*>> declPlacesSymbolByFile;
//TYPE: 0 - local, 1 - common, 2 - module, 3 - function parameter
// PAIR<TYPE, NAME>
PAIR<arrayLocation, STRING> locationPos;
VECTOR<VECTOR<PAIR<int, int>>> allShadowSpecs;
SET<STRING> containsInRegions;
// file -> lines
MAP<STRING, SET<int>> usagePlaces;
VECTOR<bool> mappedDims;
VECTOR<bool> depracateToDistribute;
bool ompThreadPrivate;
bool privateInLoop;
bool inEquivalence;
private:
TemplateLink* getTemlateInfo(const uint64_t regionId, bool withCheck = false)
{
auto it = templateInfo.find(regionId);
TemplateLink *currLink = NULL;
if (it == templateInfo.end())
{
#if __SPF
if (withCheck && sharedMemoryParallelization != 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
#endif
currLink = new TemplateLink(dimSize);
templateInfo[regionId] = currLink;
}
else
currLink = it->second;
return currLink;
}
void GenUniqKey()
{
uniqKey = shortName + locationPos.second + TO_STR(dimSize);
for (auto &place : declPlaces)
uniqKey += place.first + TO_STR(place.second);
}
//clones of template for realignes
MAP<VECTOR<dist>, STRING> templateClones;
VECTOR<int> templateDimsOrder;
public:
Array()
{
isTemplFlag = false;
isLoopArrayFlag = false;
isNonDistribute = NO_DISTR;
typeSize = 0;
uniqKey = "";
dimSize = 0;
id = -1;
declSymbol = NULL;
ompThreadPrivate = false;
privateInLoop = false;
inEquivalence = false;
}
Array(const STRING &name, const STRING &shortName, const int dimSize, const unsigned id,
const STRING &declFile, const int declLine, const PAIR<arrayLocation, STRING> &locationPos,
Symbol *declSymbol, bool inOmpThreadPriv, bool privateInLoop, bool inEquivalence,
const VECTOR<STRING> &regions, const int typeSize, const distFlag flag = DISTR) :
name(name), dimSize(dimSize), id(id), shortName(shortName),
isTemplFlag(false), isNonDistribute(flag), isLoopArrayFlag(false),
locationPos(locationPos), declSymbol(declSymbol), typeSize(typeSize),
ompThreadPrivate(inOmpThreadPriv), privateInLoop(privateInLoop), inEquivalence(inEquivalence)
{
declPlaces.insert(std::make_pair(declFile, declLine));
sizes.resize(dimSize);
sizesExpr.resize(dimSize);
mappedDims.resize(dimSize);
depracateToDistribute.resize(dimSize);
for (int z = 0; z < dimSize; ++z)
{
sizes[z] = std::make_pair((int)INT_MAX, (int)INT_MIN);
PAIR<int, int> initVal = std::make_pair(0, 0);
sizesExpr[z] = std::make_pair(std::make_pair((Expression*)NULL, initVal), std::make_pair((Expression*)NULL, initVal));
mappedDims[z] = false;
depracateToDistribute[z] = false;
}
GenUniqKey();
for (auto &reg : regions)
containsInRegions.insert(reg);
}
Array(const Array &copy)
{
id = copy.id;
name = copy.name;
shortName = copy.shortName;
dimSize = copy.dimSize;
typeSize = copy.typeSize;
sizes = copy.sizes;
sizesExpr = copy.sizesExpr;
isTemplFlag = copy.isTemplFlag;
isNonDistribute = copy.isNonDistribute;
isLoopArrayFlag = copy.isLoopArrayFlag;
declPlaces = copy.declPlaces;
locationPos = copy.locationPos;
allShadowSpecs = copy.allShadowSpecs;
for (auto &elem : copy.templateInfo)
templateInfo[elem.first] = new TemplateLink(*elem.second);
declSymbol = copy.declSymbol;
uniqKey = copy.uniqKey;
containsInRegions = copy.containsInRegions;
mappedDims = copy.mappedDims;
depracateToDistribute = copy.depracateToDistribute;
ompThreadPrivate = copy.ompThreadPrivate;
privateInLoop = copy.privateInLoop;
inEquivalence = copy.inEquivalence;
}
bool RemoveUnpammedDims()
{
bool needToRemove = false;
int countToRem = 0;
for (int z = 0; z < dimSize; ++z)
{
if (!mappedDims[z] || depracateToDistribute[z])
{
needToRemove = true;
countToRem++;
//break;
}
}
if (needToRemove == false)
return false;
if (countToRem == dimSize)
return true;
VECTOR<PAIR<int, int>> newSizes;
VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>> newSizesExpr;
VECTOR<bool> newMappedDims;
VECTOR<bool> newDepr;
for (int z = 0; z < dimSize; ++z)
{
if (mappedDims[z] && !depracateToDistribute[z])
{
newSizes.push_back(sizes[z]);
newSizesExpr.push_back(sizesExpr[z]);
newMappedDims.push_back(mappedDims[z]);
newDepr.push_back(depracateToDistribute[z]);
}
}
sizes = newSizes;
sizesExpr = newSizesExpr;
mappedDims = newMappedDims;
depracateToDistribute = newDepr;
dimSize = (int)sizes.size();
return false;
}
int GetDimSize() const { return dimSize; }
const STRING GetName() const { return name; }
const STRING GetShortName() const { return shortName; }
const STRING GetNameInLocation(void* location) const;
void* GetNameInLocationS(void* location) const;
unsigned GetId() const { return id; }
void SetSizes(VECTOR<PAIR<int, int>> &_sizes, bool notCopyToExpr = false)
{
sizes = _sizes;
if (!notCopyToExpr)
{
for (int i = 0; i < sizesExpr.size(); ++i)
{
sizesExpr[i].first.second.first = sizes[i].first;
sizesExpr[i].second.second.first = sizes[i].second;
}
}
}
const VECTOR<PAIR<int, int>>& GetSizes();
const VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>>& GetSizesExpr();
void SetTemplateFlag(const bool templFlag) { isTemplFlag = templFlag; }
bool IsTemplate() const { return isTemplFlag; }
bool IsLoopArray() const { return isLoopArrayFlag; }
bool IsArray() const { return !isTemplFlag && !isLoopArrayFlag; }
void SetLoopArray(const bool flag) { isLoopArrayFlag = flag; }
void SetSizesExpr(const VECTOR<PAIR<Expression*, Expression*>> &_sizesExpr)
{
for (int i = 0; i < _sizesExpr.size(); ++i)
{
sizesExpr[i].first.first = _sizesExpr[i].first;
sizesExpr[i].second.first = _sizesExpr[i].second;
}
}
int AddLinkWithTemplate(const int dimNum, const int dimTempl, Array *templateArray_, const PAIR<int, int> &rule, const uint64_t regionId)
{
int err = 0;
if (dimNum >= dimSize)
err = -1;
else
{
TemplateLink *currLink = getTemlateInfo(regionId, templateArray_ == NULL);
currLink->AddRule(dimNum, dimTempl, rule, templateArray_);
}
return err;
}
VECTOR<int> GetLinksWithTemplate(const uint64_t regionId)
{
TemplateLink *currLink = getTemlateInfo(regionId, true);
return currLink->GetLinks();
}
VECTOR<PAIR<int, int>> GetAlignRulesWithTemplate(const uint64_t regionId)
{
TemplateLink *currLink = getTemlateInfo(regionId, true);
return currLink->GetAlignRules();
}
bool HasTemplateInfo(const uint64_t regionId) const
{
auto it = templateInfo.find(regionId);
return (it != templateInfo.end());
}
void ChangeName(const STRING &newName)
{
auto pos = name.find(shortName);
if (pos != STRING::npos)
{
name.erase(pos, shortName.size());
shortName = newName;
name += newName;
}
GenUniqKey();
}
void ExtendDimSize(const int dim, const PAIR<int, int> &size)
{
/*if (size.first == size.second)
return;*/
sizes[dim].first = std::min(sizes[dim].first, size.first);
sizes[dim].second = std::max(sizes[dim].second, size.second);
PAIR<int, int> &left = sizesExpr[dim].first.second;
PAIR<int, int> &right = sizesExpr[dim].second.second;
left.second = std::min(left.second, sizes[dim].first - left.first);
right.second = std::max(right.second, sizes[dim].second - right.first);
}
void SetId(const unsigned newId) { id = newId; }
const SET<PAIR<STRING, int>>& GetDeclInfo() const { return declPlaces; }
const MAP<PAIR<STRING, int>, Symbol*>& GetDeclInfoWithSymb() const { return declPlacesSymbol; }
void AddDeclInfo(const PAIR<STRING, int> &declInfo, const SET<STRING>& allFilesInProj,
const STRING& currFile, Symbol* symb = NULL)
{
declPlaces.insert(declInfo);
if (symb)
{
declPlacesSymbol[declInfo] = symb;
if (allFilesInProj.find(declInfo.first) == allFilesInProj.end()) // from include
declPlacesSymbolByFile[currFile][declInfo] = symb;
}
GenUniqKey();
}
//save request of shadow spec
void ExtendShadowSpec(const VECTOR<PAIR<int, int>> &newSpec)
{
if (allShadowSpecs.size() == 0)
allShadowSpecs.resize(dimSize);
const PAIR<int, int> zeroPair(0, 0);
for (int i = 0; i < newSpec.size(); ++i)
if (newSpec[i] != zeroPair)
allShadowSpecs[i].push_back(newSpec[i]);
}
//remove last requst of shadow spec
void RemoveShadowSpec(const VECTOR<PAIR<int, int>> &delSpec)
{
int dimN = 0;
for (auto &group : allShadowSpecs)
{
for (int i = 0; i < group.size(); ++i)
{
if (group[i] == delSpec[dimN])
{
group.erase(group.begin() + i);
break;
}
}
++dimN;
}
}
//construct shadow spec from all requests
const VECTOR<PAIR<int, int>> GetShadowSpec() const
{
VECTOR<PAIR<int, int>> shadowSpec;
shadowSpec.resize(dimSize);
for (int i = 0; i < dimSize; ++i)
shadowSpec[i] = std::make_pair(0, 0);
int dimN = 0;
for (auto &group : allShadowSpecs)
{
for (auto &elem : group)
{
shadowSpec[dimN].first = std::max(shadowSpec[dimN].first, elem.first);
shadowSpec[dimN].second = std::max(shadowSpec[dimN].second, elem.second);
}
++dimN;
}
return shadowSpec;
}
void ClearShadowSpecs() { allShadowSpecs.clear(); }
STRING toString()
{
STRING retVal = "";
retVal += TO_STR(id);
retVal += "#" + name;
retVal += "#" + shortName;
retVal += "#" + TO_STR(dimSize);
retVal += "#" + TO_STR(typeSize);
retVal += "#" + TO_STR(isNonDistribute);
retVal += "#" + TO_STR(locationPos.first);
retVal += "#" + locationPos.second;
retVal += "#" + TO_STR(sizes.size());
for (int i = 0; i < sizes.size(); ++i)
retVal += "#" + TO_STR(sizes[i].first) + "#" + TO_STR(sizes[i].second);
retVal += "#" + TO_STR(depracateToDistribute.size());
for (int i = 0; i < depracateToDistribute.size(); ++i)
retVal += "#" + TO_STR((int)depracateToDistribute[i]);
retVal += "#" + TO_STR(mappedDims.size());
for (int i = 0; i < mappedDims.size(); ++i)
retVal += "#" + TO_STR((int)mappedDims[i]);
retVal += "#" + TO_STR(templateInfo.size());
for (auto it = templateInfo.begin(); it != templateInfo.end(); ++it)
retVal += "#" + TO_STR(it->first) + it->second->toString();
retVal += "#" + TO_STR((int)isTemplFlag);
retVal += "|" + TO_STR((int)isLoopArrayFlag);
retVal += "|" + TO_STR(declPlaces.size());
for (auto &place : declPlaces)
retVal += "|" + place.first + "|" + TO_STR(place.second);
retVal += "|" + TO_STR(containsInRegions.size());
for (auto &reg : containsInRegions)
retVal += "|" + reg;
return retVal;
}
Array* GetTemplateArray(const uint64_t regionId, bool withCheck = true)
{
TemplateLink *currLink = getTemlateInfo(regionId, withCheck);
return currLink->GetTemplateArray();
}
void SetDistributeFlag(const distFlag isNonDistribute_) { isNonDistribute = isNonDistribute_; }
bool IsNotDistribute() const { return (isNonDistribute == DISTR) ? false : true; }
distFlag GetDistributeFlagVal() const { return isNonDistribute; }
void ChangeLocation(arrayLocation loc, const STRING &name)
{
locationPos = std::make_pair(loc, name);
}
void SetLocation(arrayLocation loc, const STRING &name)
{
ChangeLocation(loc, name);
GenUniqKey();
}
PAIR<arrayLocation, STRING> GetLocation() const { return locationPos; }
Symbol* GetDeclSymbol(const STRING& file, const PAIR<int, int>& range, const SET<STRING>& allFilesInProj) const
{
if (!IsArray() || locationPos.first != l_COMMON)
return declSymbol;
for (auto& pos : declPlacesSymbol)
{
if (pos.first.first == file)
{
const int line = pos.first.second;
if (range.first <= line && line <= range.second)
return pos.second;
} // may be in include?
else if (allFilesInProj.find(pos.first.first) == allFilesInProj.end() && allFilesInProj.size())
{
auto it = declPlacesSymbolByFile.find(file);
if (it != declPlacesSymbolByFile.end() && it->second.find(pos.first) != it->second.end())
{
auto s = it->second.find(pos.first);
return s->second;
}
else
#if __SPF
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
#else
return NULL;
#endif
return NULL;
}
}
#if __SPF
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
#endif
return NULL;
}
Symbol* GetDeclSymbol() const { return declSymbol; }
void SetDeclSymbol(Symbol *s) { declSymbol = s; }
const STRING& GetArrayUniqKey() const { return uniqKey; }
STRING GetIndepUniqName() const { return shortName + locationPos.second + TO_STR(dimSize); }
const SET<STRING>& GetRegionsName() const { return containsInRegions; }
void SetRegionPlace(const STRING &regName) { if (regName != "") containsInRegions.insert(regName); }
const MAP<STRING, SET<int>>& GetUsagePlaces() const { return usagePlaces; }
const SET<int> GetUsagePlaces(const STRING& fileName, const PAIR<int, int>* filter = NULL) const
{
auto it = usagePlaces.find(fileName);
if (it == usagePlaces.end())
return SET<int>();
if (!filter)
return it->second;
else
{
SET<int> ret;
int first = filter->first;
int last = filter->second;
for (auto& elem : it->second)
if (first <= elem && elem <= last)
ret.insert(elem);
return ret;
}
}
void AddUsagePlace(const STRING &fileName, int lineNumber)
{
auto it = usagePlaces.find(fileName);
if (it == usagePlaces.end())
it = usagePlaces.insert(it, make_pair(fileName, SET<int>()));
it->second.insert(lineNumber);
}
void SetMappedDim(const int dim)
{
if (dim >= dimSize)
return;
mappedDims[dim] = true;
}
bool IsDimMapped(const int dim) const
{
if (dim >= dimSize)
return false;
else
{
if (templateDimsOrder.size() == 0)
return mappedDims[dim];
else
return mappedDims[templateDimsOrder[dim]];
}
}
void DeprecateDimension(const int dim, bool value = true)
{
if (dim >= dimSize)
return;
depracateToDistribute[dim] = value;
}
void DeprecateAllDims()
{
for (int dim = 0; dim < dimSize; ++dim)
depracateToDistribute[dim] = true;
}
bool IsDimDepracated(const int dim) const
{
if (dim >= dimSize)
return false;
else
{
if (templateDimsOrder.size() == 0)
return depracateToDistribute[dim];
else
return depracateToDistribute[templateDimsOrder[dim]];
}
}
bool IsAllDeprecated() const
{
bool ret = true;
for (int z = 0; z < dimSize; ++z)
ret = ret && depracateToDistribute[z];
return ret;
}
const VECTOR<bool>& GetDeprecetedDims() const { return depracateToDistribute; }
int GetTypeSize() const { return typeSize; }
STRING AddTemplateClone(const VECTOR<dist> &newDist)
{
auto it = templateClones.find(newDist);
if (it == templateClones.end())
it = templateClones.insert(it, std::make_pair(newDist, shortName + STRING("_r") + TO_STR(templateClones.size())));
return it->second;
}
void ClearTemplateClones()
{
templateClones.clear();
templateDimsOrder.clear();
orderedSizes.clear();
orderedSizesExpr.clear();
}
const MAP<VECTOR<dist>, STRING>& GetAllClones() const { return templateClones; }
void AddNewTemplateDimsOrder(const VECTOR<int> &newOrder) { templateDimsOrder = newOrder; }
VECTOR<int> GetNewTemplateDimsOrder() const { return templateDimsOrder; }
void SetDimSizesToMaxMin(bool notCopyToExpr = false)
{
for (int i = 0; i < dimSize; ++i)
sizes[i] = std::make_pair((int)INT_MAX, (int)INT_MIN);
if (!notCopyToExpr)
{
for (int i = 0; i < sizesExpr.size(); ++i)
{
sizesExpr[i].first.second.first = sizes[i].first;
sizesExpr[i].second.second.first = sizes[i].second;
}
}
}
bool IsOmpThreadPrivate() const { return ompThreadPrivate; }
bool IsSpfPrivate() const { return ((isNonDistribute == SPF_PRIV) || (isNonDistribute == IO_PRIV)); }
bool IsInEquvalence() const { return inEquivalence; }
void SetEquvalence(bool value) { inEquivalence = value; }
bool IsPrivateInLoop() const { return privateInLoop; }
void SetPrivateInLoopStatus(bool value) { privateInLoop = value; }
bool IsModuleSymbol() const { return locationPos.first == l_MODULE; }
~Array()
{
for (auto &templ : templateInfo)
delete templ.second;
}
};
struct ArrayComparator
{
bool operator()(const Array* left, const Array* right) const
{
return (left->GetArrayUniqKey() > right->GetArrayUniqKey());
}
};
struct UnaryAccess
{
UnaryAccess()
{
line = -1;
type = -1;
underFunctionPar = -1;
fName = "";
count = 0;
}
UnaryAccess(const PAIR<int, char>& info)
{
line = info.first;
type = info.second;
underFunctionPar = -1;
fName = "";
count = 1;
}
UnaryAccess(const PAIR<int, char>& info, const STRING &f, const int parN)
{
line = info.first;
type = info.second;
underFunctionPar = parN;
fName = f;
count = 1;
}
STRING PrintInfo() const
{
STRING out = "#" + std::to_string(count) + " of ";
if (type == 0)
out += "READ ";
else if(type == 1)
out += "WRITE ";
else
out += "UNKN ";
out += "on line " + std::to_string(line);
if (underFunctionPar != -1)
out += " in '#" + std::to_string(underFunctionPar + 1) + "' par of function call '" + fName + "'";
return out;
}
bool operator==(const UnaryAccess &left) const
{
return (line == left.line && type == left.type &&
underFunctionPar == left.underFunctionPar && fName == left.fName);
}
bool operator!=(const UnaryAccess& left) const
{
return !(*this == left);
}
int line;
int type; // R/W -> 0, 1
int underFunctionPar;
STRING fName;
int count;
};
class ArrayAccessInfo
{
private:
MAP<STRING, MAP<int, VECTOR<UnaryAccess>>> accessPatterns; // file -> MAP<LINE, info>
public:
void AddAccessInfo(const STRING& file, const PAIR<int, char> &info, const STRING fName = "", int underParN = -1)
{
auto it = accessPatterns.find(file);
if (it == accessPatterns.end())
it = accessPatterns.insert(it, std::make_pair(file, MAP<int, VECTOR<UnaryAccess>>()));
bool found = false;
UnaryAccess toAdd;
if (underParN == -1)
toAdd = UnaryAccess(info);
else
toAdd = UnaryAccess(info, fName, underParN);
auto itMap = it->second.find(info.first);
if (itMap == it->second.end())
it->second[info.first].push_back(toAdd);
else
{
for (int z = 0; z < itMap->second.size(); ++z)
{
if (itMap->second[z] == toAdd)
{
found = true;
itMap->second[z].count++;
break;
}
}
if (found == false)
{
if (underParN == -1)
itMap->second.push_back(toAdd);
else
itMap->second.push_back(toAdd);
}
}
}
void checkAndUpdate(const MAP<STRING, FuncInfo*>& allFuncs);
const MAP<STRING, MAP<int, VECTOR<UnaryAccess>>>& GetAllAccessInfo() const { return accessPatterns; }
const MAP<int, VECTOR<UnaryAccess>>* GetAccessInfoByFile(const STRING &file) const
{
auto it = accessPatterns.find(file);
if (it == accessPatterns.end())
return NULL;
else
return &(it->second);
}
};
void printArrayInfo(const STRING &file, const MAP<std::tuple<int, STRING, STRING>, PAIR<Array*, ArrayAccessInfo*>> &declaredArrays);
void fixTypeOfArrayInfoWithCallGraph(MAP<std::tuple<int, STRING, STRING>, PAIR<Array*, ArrayAccessInfo*>>& declaredArrays, const MAP<STRING, FuncInfo*>& allFuncs);
}
#undef VECTOR
#undef STRING
#undef PAIR
#undef MAP
#undef SET
#undef TO_STR

View File

@@ -0,0 +1,766 @@
#include "Array.h"
#include "../Utils/errors.h"
#include "../Utils/utils.h"
#include "../GraphCall/graph_calls.h"
#include "../Utils/SgUtils.h"
#include "../DirectiveProcessing/directive_parser.h"
#include "../DirectiveProcessing/directive_omp_parser.h"
#include "../LoopAnalyzer/loop_analyzer.h"
using namespace std;
extern int ignoreIO;
extern map<DIST::Array*, std::tuple<int, string, string>> tableOfUniqNamesByArray;
static set<tuple<int, string, string>> checkedArraysForWrongLocation;
static bool findOmpThreadPrivDecl(SgStatement* st, map<SgStatement*, set<string>>& ompThreadPrivate, SgSymbol* toFind)
{
auto it = ompThreadPrivate.find(st);
if (it == ompThreadPrivate.end())
{
it = ompThreadPrivate.insert(it, make_pair(st, set<string>()));
SgStatement* lastN = st->lastNodeOfStmt();
set<string> dummy;
do
{
st = st->lexNext();
auto res = parseOmpInStatement(st, dummy);
for (auto& dir : res)
for (auto& var : dir.threadPrivVars)
it->second.insert(var);
} while (st != lastN && !isSgExecutableStatement(st) && st->variant() != CONTAINS_STMT);
}
if (it->second.find(toFind->identifier()) != it->second.end())
return true;
else
return false;
}
static bool hasAssingOpInDecl(SgSymbol* symb)
{
vector<SgStatement*> allDecls;
SgStatement* decl = declaratedInStmt(symb, &allDecls);
for (auto& elem : allDecls)
{
if (elem->variant() == VAR_DECL_90)
{
SgExpression* list = elem->expr(0);
while (list)
{
if (list->lhs()->variant() == ASSGN_OP)
if (list->lhs()->lhs()->symbol() && OriginalSymbol(list->lhs()->lhs()->symbol()) == symb)
return true;
list = list->rhs();
}
}
}
return false;
}
static string getNameWithScope(SgStatement* scope, const string& currFunctionName)
{
if (scope && isSgProgHedrStmt(scope) && scope->symbol()->identifier() != currFunctionName)
return scope->symbol()->identifier();
else
return currFunctionName;
}
struct findInfo
{
findInfo(const string fName, SgExpression* ex, int parN, bool isWrite) :
fName(fName), ex(ex), parN(parN), isWrite(isWrite)
{ }
SgExpression* ex;
string fName;
int parN;
bool isWrite;
};
static void findArrayRefs (SgExpression* ex, SgStatement* st, string fName, int parN, bool isWrite,
const map<string, vector<SgExpression*>>& commonBlocks,
map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays,
map<SgStatement*, set<tuple<int, string, string>>>& declaratedArraysSt,
const set<string>& privates, const set<string>& deprecatedByIO,
bool isExecutable, const string& currFunctionName,
const vector<string>& inRegion,
const set<string>& funcParNames,
map<SgStatement*, set<string>>& ompThreadPrivate,
const map<string, int>& distrStateFromGUI,
const bool saveAllLocals,
map<string, vector<Messages>>& currMessages,
int& errorCount)
{
const string globalFile = current_file->filename();
const set<string> filesInProj = getAllFilesInProject();
if (ex == NULL)
return;
stack<findInfo> queue;
queue.push(findInfo(fName, ex, parN, isWrite));
while (!queue.empty())
{
const findInfo& curQ = queue.top();
ex = curQ.ex;
fName = curQ.fName;
parN = curQ.parN;
isWrite = curQ.isWrite;
queue.pop();
if (isArrayRef(ex))
{
SgSymbol* symb = OriginalSymbol(ex->symbol());
const bool inDataStat = (symb->attributes() & DATA_BIT) != 0 || ((ex->symbol())->attributes() & DATA_BIT);
checkNull(symb->type(), convertFileName(__FILE__).c_str(), __LINE__);
const int typeSize = getSizeOfType(symb->type()->baseType());
if (typeSize == 0)
{
//__spf_print(1, "Wrong type size for array %s\n", symb->identifier());
//printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
SgStatement* decl = declaratedInStmt(symb);
if (decl->variant() == DVM_VAR_DECL || decl->variant() == HPF_TEMPLATE_STAT)
{
const string tmp(decl->unparse());
if (tmp.find("!DVM$ TEMPLATE") != string::npos)
{
auto sTemp = symb->identifier();
tuple<int, string, string> uniqKey;
bool found = false;
for (auto& elem : declaredArrays)
{
if (elem.second.first->GetShortName() == sTemp)
{
uniqKey = elem.first;
found = true;
}
}
if (found)
{
auto itDecl = declaratedArraysSt.find(decl);
if (itDecl == declaratedArraysSt.end())
itDecl = declaratedArraysSt.insert(itDecl, make_pair(decl, set<tuple<int, string, string>>()));
itDecl->second.insert(uniqKey);
return;
}
}
}
auto uniqKey = getUniqName(commonBlocks, decl, symb);
SgStatement* scope = symb->scope();
pair<DIST::arrayLocType, string> arrayLocation;
string typePrefix = "";
while (scope && scope->variant() == STRUCT_DECL)
{
if (typePrefix == "")
typePrefix = scope->symbol()->identifier();
else
typePrefix += scope->symbol()->identifier() + string("::");
scope = scope->controlParent();
}
if ((ex->symbol() && symb != ex->symbol()) || (scope && scope->variant() == MODULE_STMT))
{
if (scope)
{
string modName = scope->symbol()->identifier();
arrayLocation = make_pair(DIST::l_MODULE, (typePrefix == "") ? modName : modName + "::" + typePrefix);
}
else //TODO: find module name with another way
arrayLocation = make_pair(DIST::l_MODULE, "UNREC_MODULE_NAME");
}
else if (get<1>(uniqKey).find("common_") != string::npos)
arrayLocation = make_pair(DIST::l_COMMON, get<1>(uniqKey).substr(strlen("common_")));
else if (funcParNames.find(symb->identifier()) != funcParNames.end())
arrayLocation = make_pair(DIST::l_PARAMETER, getNameWithScope(scope, currFunctionName));
else
{
if (saveAllLocals || ((symb->attributes() & SAVE_BIT) != 0) || hasAssingOpInDecl(symb))
arrayLocation = make_pair(DIST::l_LOCAL_SAVE, getNameWithScope(scope, currFunctionName));
else
arrayLocation = make_pair(DIST::l_LOCAL, getNameWithScope(scope, currFunctionName));
}
auto itNew = declaredArrays.find(uniqKey);
if (itNew == declaredArrays.end())
{
DIST::Array* arrayToAdd =
new DIST::Array(getShortName(uniqKey), symb->identifier(), ((SgArrayType*)(symb->type()))->dimension(),
getUniqArrayId(), decl->fileName(), decl->lineNumber(), arrayLocation, new Symbol(symb),
findOmpThreadPrivDecl(scope, ompThreadPrivate, symb), false, false,
inRegion, typeSize, sharedMemoryParallelization ? DIST::NO_DISTR : DIST::DISTR);
itNew = declaredArrays.insert(itNew, make_pair(uniqKey, make_pair(arrayToAdd, new DIST::ArrayAccessInfo())));
vector<pair<int, int>> sizes;
map<DIST::Array*, set<DIST::Array*>> arrayLinksByFuncCallsNotReady;
map<string, vector<FuncInfo*>> allFuncInfoNoReady;
auto sizesExpr = getArraySizes(sizes, symb, decl, arrayLinksByFuncCallsNotReady, allFuncInfoNoReady);
arrayToAdd->SetSizes(sizes);
arrayToAdd->SetSizesExpr(sizesExpr);
tableOfUniqNamesByArray[arrayToAdd] = uniqKey;
}
else // check the same location from include!
{
auto prevLocation = itNew->second.first->GetLocation();
if (prevLocation != arrayLocation)
{
if (checkedArraysForWrongLocation.find(uniqKey) == checkedArraysForWrongLocation.end())
{
checkedArraysForWrongLocation.insert(uniqKey);
__spf_print(1, "can not change declaration area of array '%s' on line %d\n", symb->identifier(), st->lineNumber());
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Array '%s' has declaration area conflict, it might be worth applying the Include inlining pass", to_wstring(symb->identifier()).c_str());
__spf_printToLongBuf(messageR, R184, to_wstring(symb->identifier()).c_str());
currMessages[st->fileName()].push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1061));
}
errorCount++;
}
}
if ((symb->attributes() & EQUIVALENCE_BIT) != 0)
itNew->second.first->SetEquvalence(true);
for (auto& reg : inRegion)
itNew->second.first->SetRegionPlace(reg);
const auto oldVal = itNew->second.first->GetDistributeFlagVal();
bool isarrayInModule = (itNew->second.first->GetLocation().first == DIST::l_MODULE);
if (oldVal == DIST::DISTR || oldVal == DIST::NO_DISTR)
{
if (itNew->second.first->IsOmpThreadPrivate())
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
else if (privates.find(symb->identifier()) != privates.end() || isarrayInModule)
{
//check in module
if (itNew->second.first->GetLocation().first == DIST::l_MODULE)
{
for (auto& data : getAttributes<SgStatement*, SgStatement*>(decl, set<int>{ SPF_ANALYSIS_DIR }))
{
set<string> privatesS;
fillPrivatesFromComment(new Statement(data), privatesS);
if (privatesS.find(symb->identifier()) != privatesS.end())
{
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
break;
}
}
auto prev = decl->lexPrev();
checkNull(prev, convertFileName(__FILE__).c_str(), __LINE__);
set<string> privatesS;
fillPrivatesFromComment(new Statement(prev), privatesS);
if (privatesS.find(symb->identifier()) != privatesS.end())
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
}
else
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
}
else if (deprecatedByIO.find(symb->identifier()) != deprecatedByIO.end())
itNew->second.first->SetDistributeFlag(DIST::IO_PRIV);
else if (isSgConstantSymb(symb) || inDataStat)
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
else
{
auto it = distrStateFromGUI.find(itNew->second.first->GetIndepUniqName());
if (it != distrStateFromGUI.end())
{
if (it->second != oldVal)
{
itNew->second.first->SetDistributeFlag((DIST::distFlag)it->second);
__spf_print(1, "change flag for array from cache '%s': %d -> %d\n", it->first.c_str(), oldVal, it->second);
}
}
else
itNew->second.first->SetDistributeFlag(DIST::DISTR);
}
}
if (typeSize == 0) // unknown
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
if (!isExecutable)
itNew->second.first->AddDeclInfo(make_pair(st->fileName(), st->lineNumber()), filesInProj, globalFile, new Symbol(symb));
if (isExecutable)
{
if (st->variant() != ALLOCATE_STMT && st->variant() != DEALLOCATE_STMT)
{
itNew->second.second->AddAccessInfo(st->fileName(), make_pair(st->lineNumber(), isWrite ? 1 : 0), fName, parN);
itNew->second.first->AddUsagePlace(st->fileName(), st->lineNumber());
}
}
auto itDecl = declaratedArraysSt.find(decl);
if (itDecl == declaratedArraysSt.end())
itDecl = declaratedArraysSt.insert(itDecl, make_pair(decl, set<tuple<int, string, string>>()));
itDecl->second.insert(uniqKey);
if (decl->variant() == DVM_VAR_DECL || decl->variant() == HPF_TEMPLATE_STAT)
{
const string tmp(decl->unparse());
if (tmp.find("!DVM$ TEMPLATE") != string::npos)
{
itNew->second.first->SetTemplateFlag(true);
//TODO: analyze align mapping
for (int z = 0; z < itNew->second.first->GetDimSize(); ++z)
itNew->second.first->SetMappedDim(z);
}
}
}
if (ex->variant() == FUNC_CALL)
{
SgFunctionCallExp* funcExp = (SgFunctionCallExp*)ex;
const string fName = funcExp->funName()->identifier();
bool intr = (isIntrinsicFunctionName(fName.c_str()) == 1);
for (int z = 0; z < funcExp->numberOfArgs(); ++z)
{
//assume all arguments of function as OUT, except for inctrinsics
bool isWriteN = intr ? false : true;
//need to correct W/R usage with GraphCall map later
findArrayRefs(funcExp->arg(z), st, fName, z, isWriteN, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO, isExecutable, currFunctionName, inRegion, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals, currMessages, errorCount);
}
}
else
{
bool isWriteN = false;
if (ex->lhs())
queue.push(findInfo("", ex->lhs(), -1, isWriteN));
if (ex->rhs())
queue.push(findInfo("", ex->rhs(), -1, isWriteN));
//findArrayRefs(ex->lhs(), st, "", -1, isWriteN, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO, isExecutable, currFunctionName, inRegion, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals, currMessages, errorCount);
//findArrayRefs(ex->rhs(), st, "", -1, isWriteN, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO, isExecutable, currFunctionName, inRegion, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals, currMessages, errorCount);
}
}
}
static void findArrayRefInIO(SgExpression* ex, set<string>& deprecatedByIO, SgStatement* st, map<string, vector<Messages>>& currMessages)
{
if (ex)
{
if (ex->variant() == ARRAY_REF)
{
auto symb = ex->symbol();
if (symb->type())
{
if (symb->type()->variant() == T_ARRAY)
{
auto found = deprecatedByIO.find(OriginalSymbol(symb)->identifier());
if (found == deprecatedByIO.end())
{
deprecatedByIO.insert(found, OriginalSymbol(symb)->identifier());
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of DVM's I/O constraints", to_wstring(symb->identifier()).c_str());
__spf_printToLongBuf(messageR, R68, to_wstring(symb->identifier()).c_str());
currMessages[st->fileName()].push_back(Messages(WARR, st->lineNumber(), messageR, messageE, 1037));
__spf_print(1, "Array '%s' at line %d can not be distributed because of DVM's I/O constraints\n", symb->identifier(), st->lineNumber());
}
}
}
}
findArrayRefInIO(ex->lhs(), deprecatedByIO, st, currMessages);
findArrayRefInIO(ex->rhs(), deprecatedByIO, st, currMessages);
}
}
static void findReshape(SgStatement* st, set<string>& privates, map<string, vector<Messages>>& currMessages)
{
if (st->variant() == ASSIGN_STAT)
{
SgExpression* exL = st->expr(0);
SgExpression* exR = st->expr(1);
if (exR->variant() == FUNC_CALL && exL->variant() == ARRAY_REF)
{
if (exR->symbol()->identifier() == string("reshape"))
{
if (privates.find(exL->symbol()->identifier()) == privates.end())
{
privates.insert(exL->symbol()->identifier());
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of RESHAPE", to_wstring(exL->symbol()->identifier()).c_str());
__spf_printToLongBuf(messageR, R90, to_wstring(exL->symbol()->identifier()).c_str());
currMessages[st->fileName()].push_back(Messages(NOTE, st->lineNumber(), messageR, messageE, 1047));
}
}
}
}
}
static void findConstructorRef(SgStatement* st, set<string>& privates, map<string, vector<Messages>>& currMessages)
{
if (st->variant() == ASSIGN_STAT)
{
SgExpression* exL = st->expr(0);
SgExpression* exR = st->expr(1);
if (exR->variant() == CONSTRUCTOR_REF && exL->variant() == ARRAY_REF)
{
if (privates.find(exL->symbol()->identifier()) == privates.end())
{
privates.insert(exL->symbol()->identifier());
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of initializer list", to_wstring(exL->symbol()->identifier()).c_str());
__spf_printToLongBuf(messageR, R164, to_wstring(exL->symbol()->identifier()).c_str());
currMessages[st->fileName()].push_back(Messages(NOTE, st->lineNumber(), messageR, messageE, 1047));
}
}
}
}
static void addPrivates(SgStatement* st, set<string>& privates, map<string, set<Symbol*>>& reductions,
map<string, set<tuple<Symbol*, Symbol*, int>>>& reductionsLoc)
{
//after SPF preprocessing
for (auto& data : getAttributes<SgStatement*, SgStatement*>(st, set<int>{ SPF_ANALYSIS_DIR }))
{
set<Symbol*> privatesS;
fillPrivatesFromComment(new Statement(data), privatesS);
fillReductionsFromComment(new Statement(data), reductions);
fillReductionsFromComment(new Statement(data), reductionsLoc);
for (auto& elem : privatesS)
privates.insert(elem->GetOriginal()->identifier());
}
//before SPF preprocessing
if (st->variant() == SPF_ANALYSIS_DIR)
{
set<Symbol*> privatesS;
fillPrivatesFromComment(new Statement(st), privatesS);
fillReductionsFromComment(new Statement(st), reductions);
fillReductionsFromComment(new Statement(st), reductionsLoc);
for (auto& elem : privatesS)
privates.insert(elem->GetOriginal()->identifier());
}
}
int getAllDeclaredArrays(SgFile* file, map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays,
map<SgStatement*, set<tuple<int, string, string>>>& declaratedArraysSt, map<string, vector<Messages>>& currMessages,
const vector<ParallelRegion*>& regions, const map<string, int>& distrStateFromGUI)
{
int countErrors = 0;
vector<SgStatement*> modules;
findModulesInFile(file, modules);
map<string, set<string>> privatesByModule;
for (auto& mod : modules)
{
const string modName = mod->symbol()->identifier();
privatesByModule[modName] = set<string>();
auto it = privatesByModule.find(modName);
for (SgStatement* iter = mod; iter != mod->lastNodeOfStmt(); iter = iter->lexNext())
{
if (iter->variant() == CONTAINS_STMT)
break;
//after SPF preprocessing
for (auto& data : getAttributes<SgStatement*, SgStatement*>(iter, set<int>{ SPF_ANALYSIS_DIR }))
fillPrivatesFromComment(new Statement(data), it->second);
//before SPF preprocessing
if (iter->variant() == SPF_ANALYSIS_DIR)
fillPrivatesFromComment(new Statement(iter), it->second);
}
}
map<SgStatement*, set<string>> ompThreadPrivate;
for (int i = 0; i < file->numberOfFunctions(); ++i)
{
bool saveAllLocals = false;
SgStatement* st = file->functions(i);
SgStatement* lastNode = st->lastNodeOfStmt();
map<string, vector<SgExpression*>> commonBlocks;
const string currFunctionName = st->symbol()->identifier();
getCommonBlocksRef(commonBlocks, st, lastNode);
set<string> privates;
set<string> deprecatedByIO;
map<string, set<Symbol*>> reductions;
map<string, set<tuple<Symbol*, Symbol*, int>>> reductionsLoc;
set<string> funcParNames;
if (st->variant() != PROG_HEDR)
{
SgProcHedrStmt* func = (SgProcHedrStmt*)st;
for (int z = 0; z < func->numberOfParameters(); ++z)
funcParNames.insert(func->parameter(z)->identifier());
if (func->nameWithContains() != func->name().identifier()) // added contains args
{
SgProcHedrStmt* cp = (SgProcHedrStmt*)func->controlParent();
checkNull(cp, convertFileName(__FILE__).c_str(), __LINE__);
for (int z = 0; z < cp->numberOfParameters(); ++z)
funcParNames.insert(cp->parameter(z)->identifier());
}
}
for (SgStatement* iter = st; iter != lastNode; iter = iter->lexNext())
{
if (iter->variant() == CONTAINS_STMT)
break;
addPrivates(iter, privates, reductions, reductionsLoc);
if (iter->variant() == USE_STMT)
fillFromModule(iter->symbol(), privatesByModule, privates);
if (iter->variant() == SAVE_DECL)
if (!iter->expr(0) && !iter->expr(1) && !iter->expr(2))
saveAllLocals = true;
}
for (SgStatement* iter = st; iter != lastNode; iter = iter->lexNext())
{
if (iter->variant() == CONTAINS_STMT)
break;
findReshape(iter, privates, currMessages);
findConstructorRef(iter, privates, currMessages);
}
SgStatement* tmpModFind = st;
while (tmpModFind->variant() != GLOBAL)
{
tmpModFind = tmpModFind->controlParent();
if (tmpModFind->variant() == MODULE_STMT)
fillFromModule(tmpModFind->symbol(), privatesByModule, privates);
}
SgStatement* currF = st;
SgStatement* contains = isSgProgHedrStmt(currF->controlParent());
if (contains)
{
for (SgStatement* loc = contains; loc; loc = loc->lexNext())
{
if (isSgExecutableStatement(loc))
break;
if (loc->variant() == CONTAINS_STMT)
break;
if (loc->variant() == USE_STMT)
fillFromModule(loc->symbol(), privatesByModule, privates);
}
}
for (auto& elem : reductions)
for (auto& setElem : elem.second)
privates.insert(setElem->identifier());
for (auto& elem : reductionsLoc)
{
for (auto& setElem : elem.second)
{
privates.insert(get<0>(setElem)->identifier());
privates.insert(get<1>(setElem)->identifier());
}
}
//analyze IO operations
if (!ignoreIO)
{
for (SgStatement* iter = st; iter != lastNode; iter = iter->lexNext())
{
if (iter->variant() == CONTAINS_STMT)
break;
SgInputOutputStmt* stIO = isSgInputOutputStmt(iter);
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, iter->fileName(), iter->lineNumber());
if (stIO && currRegs.size()) // deprecate to distribute arrays only in regions
{
int countOfItems = 0;
for (SgExpression* items = stIO->itemList(); items; items = items->rhs(), ++countOfItems);
//TODO: need to add more checkers!
if (countOfItems > 1)
{
for (SgExpression* items = stIO->itemList(); items; items = items->rhs())
findArrayRefInIO(items->lhs(), deprecatedByIO, stIO, currMessages);
}
else if (countOfItems == 1)
{
auto list = stIO->specList();
bool ok = true;
//exclude FMT='format'
while (list)
{
if (list->lhs() && list->lhs()->variant() == SPEC_PAIR)
{
auto ex = list->lhs();
if (ex->lhs() && ex->rhs())
{
if (ex->lhs()->variant() == KEYWORD_VAL)
{
SgKeywordValExp* key = (SgKeywordValExp*)(ex->lhs());
if (key->value() == string("fmt"))
if (ex->rhs()->variant() == STRING_VAL)
ok = false;
}
}
}
if (!ok)
break;
list = list->rhs();
}
//check A(i,j) for example
auto item = stIO->itemList()->lhs();
if (item->rhs() || item->lhs())
ok = false;
if (!ok)
findArrayRefInIO(item, deprecatedByIO, stIO, currMessages);
}
}
}
}
while (st != lastNode)
{
if (st->variant() == CONTAINS_STMT)
break;
if (!isSPF_stat(st) && !isDVM_stat(st))
{
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, st->fileName(), st->lineNumber());
vector<string> regNames;
for (auto& reg : currRegs)
regNames.push_back(reg->GetName());
if (regNames.size() == 0)
regNames.push_back("default");
if (st->variant() == PROC_STAT)
{
SgCallStmt* funcExp = (SgCallStmt*)st;
const string fName = funcExp->symbol()->identifier();
for (int z = 0; z < funcExp->numberOfArgs(); ++z)
{
findArrayRefs(funcExp->arg(z), st, fName, z, true,
commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
isSgExecutableStatement(st) ? true : false, currFunctionName,
regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals,
currMessages, countErrors);
}
}
else
{
for (int i = 0; i < 3; ++i)
findArrayRefs(st->expr(i), st, "", -1, (st->variant() == ASSIGN_STAT && i == 0) ? true : false,
commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
isSgExecutableStatement(st) ? true : false, currFunctionName,
regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals,
currMessages, countErrors);
}
}
st = st->lexNext();
}
}
//preprocess only module declaration
for (auto& mod : modules)
{
SgStatement* st = mod->lexNext();
SgStatement* lastNode = mod->lastNodeOfStmt();
map<string, vector<SgExpression*>> commonBlocks;
set<string> privates;
set<string> deprecatedByIO;
set<string> funcParNames;
fillFromModule(st->symbol(), privatesByModule, privates);
while (st != lastNode)
{
if (st->variant() == CONTAINS_STMT)
break;
if (!isSPF_stat(st) && !isDVM_stat(st))
{
//TODO: set clear regions for modules
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, st->fileName(), st->lineNumber());
vector<string> regNames;
for (auto& reg : currRegs)
regNames.push_back(reg->GetName());
if (regNames.size() == 0)
regNames.push_back("default");
for (int i = 0; i < 3; ++i)
findArrayRefs(st->expr(i), st, "", -1, false, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
false, "NULL", regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, false,
currMessages, countErrors);
}
st = st->lexNext();
}
}
//preprocess only block data declaration
for (SgStatement* st = file->firstStatement()->lexNext(); st; st = st->lastNodeOfStmt(), st = st->lexNext())
{
if (st->variant() == BLOCK_DATA)
{
SgStatement* last = st->lastNodeOfStmt();
SgStatement* curr = st;
map<string, vector<SgExpression*>> commonBlocks;
getCommonBlocksRef(commonBlocks, st, last);
set<string> privates;
set<string> deprecatedByIO;
set<string> funcParNames;
string blockName = "BLOCK DATA";
if (st->symbol())
blockName = st->symbol()->identifier();
while (curr && curr != last)
{
//TODO: set clear regions for block data
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, curr->fileName(), curr->lineNumber());
vector<string> regNames;
for (auto& reg : currRegs)
regNames.push_back(reg->GetName());
if (regNames.size() == 0)
regNames.push_back("default");
for (int i = 0; i < 3; ++i)
findArrayRefs(curr->expr(i), curr, "", -1, false, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
false, blockName, regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, false,
currMessages, countErrors);
curr = curr->lexNext();
}
}
}
return countErrors;
}

View File

@@ -0,0 +1,292 @@
#pragma once
#include <string>
#include <map>
#include <set>
#include "Array.h"
#define MAP std::map
#define SET std::set
#define VECTOR std::vector
#define STRING std::string
#define PAIR std::pair
namespace Distribution
{
template<typename vType>
class Arrays
{
private:
unsigned nextVertexNum;
MAP<Array*, VECTOR<vType>> numVertsInGraph;
MAP<STRING, Array*> arraysByName;
SET<Array*> arrays;
VECTOR<STRING> arrayNameByVertex;
VECTOR<PAIR<int, Array*>> arrayDimInfoByVertex;
public:
Arrays() { nextVertexNum = 0; }
Arrays(const Arrays &copy)
{
nextVertexNum = copy.nextVertexNum;
numVertsInGraph = copy.numVertsInGraph;
arraysByName = copy.arraysByName;
arrays = copy.arrays;
arrayNameByVertex = copy.arrayNameByVertex;
arrayDimInfoByVertex = copy.arrayDimInfoByVertex;
}
void UpdateLinks(const MAP<Array*, Array*> &oldNewArrays)
{
SET<Array*> newArrays;
for (auto &array : arrays)
newArrays.insert(oldNewArrays.find(array)->second);
arrays = newArrays;
for (auto &elem : arraysByName)
elem.second = oldNewArrays.find(elem.second)->second;
for (auto &elem : arrayDimInfoByVertex)
elem.second = oldNewArrays.find(elem.second)->second;
MAP<Array*, VECTOR<vType>> newNumVertsInGraph;
for (auto &elem : numVertsInGraph)
newNumVertsInGraph.insert(std::make_pair(oldNewArrays.find(elem.first)->second, elem.second));
numVertsInGraph = newNumVertsInGraph;
}
void cleanData()
{
nextVertexNum = 0;
numVertsInGraph.clear();
arraysByName.clear();
arrays.clear();
arrayNameByVertex.clear();
arrayDimInfoByVertex.clear();
}
int AddArrayToGraph(Array *array)
{
int status = 0;
auto foundIt = numVertsInGraph.find(array);
if (foundIt == numVertsInGraph.end())
{
const int dimSize = array->GetDimSize();
VECTOR<vType> vertexNum(dimSize);
for (int i = 0; i < dimSize; ++i)
{
vertexNum[i] = nextVertexNum + i;
STRING newName(array->GetName());
newName += "." + std::to_string(i);
arrayNameByVertex.push_back(newName);
arrayDimInfoByVertex.push_back(std::make_pair(i, array));
}
nextVertexNum += dimSize;
numVertsInGraph.insert(foundIt, make_pair(array, vertexNum));
arrays.insert(array);
arraysByName.insert(arraysByName.end(), make_pair(array->GetName(), array));
}
else
status = 1;
return status;
}
int GetVertNumber(Array *array, const int dimNum, vType &retVal) const
{
int err = 0;
auto foundIt = numVertsInGraph.find(array);
if (foundIt == numVertsInGraph.end())
err = -1;
else
{
const int maxDims = array->GetDimSize();
if (dimNum >= maxDims)
err = -1;
else
retVal = foundIt->second[dimNum];
}
return err;
}
int GetAllVertNumber(const Array *array, std::vector<vType> &retVal) const
{
int err = 0;
auto foundIt = numVertsInGraph.find((Array*)array);
if (foundIt == numVertsInGraph.end())
err = -1;
else
retVal = foundIt->second;
return err;
}
int GetDimNumber(const Array *array, const vType vertexN, vType &retVal) const
{
int err = 0;
auto foundIt = numVertsInGraph.find((Array*)array);
if (foundIt == numVertsInGraph.end())
err = -1;
else
{
const int maxDims = array->GetDimSize();
for (int i = 0; i < maxDims; ++i)
{
if (foundIt->second[i] == vertexN)
{
retVal = i;
return 0;
}
}
err = -1;
}
return err;
}
int GetNameByVertex(const vType vert, STRING &name) const
{
if (vert >= (vType)arrayNameByVertex.size())
return -1;
else
{
name = arrayNameByVertex[vert];
return 0;
}
}
Array* GetArrayByVertex(const vType vert) const
{
STRING name;
int res = GetNameByVertex(vert, name);
Array *retVal = NULL;
if (res != -1)
{
int count = 0;
for (int k = (int)name.size() - 1; k >= 0; --k, ++count)
{
if (name[k] == '.')
{
name[k] = '\0';
break;
}
}
name.resize(name.size() - count - 1);
retVal = GetArrayByName(name);
}
return retVal;
}
Array* GetArrayByName(const STRING &name) const
{
auto res = arraysByName.find(name);
if (res != arraysByName.end())
return res->second;
else
return NULL;
}
int GetInfoByVertex(const vType vertex, std::pair<int, Array*> &info) const
{
int err = (arrayDimInfoByVertex.size() >= vertex) ? 1 : 0;
if (arrayDimInfoByVertex.size() < vertex)
info = arrayDimInfoByVertex[vertex];
return err;
}
const SET<Array*>& GetArrays() const { return arrays; }
unsigned GetMaxVertexNum() const { return nextVertexNum; }
void SaveArraysToFile(FILE *file) const
{
if (file)
{
fprintf(file, "%d\n", nextVertexNum);
int count = numVertsInGraph.size();
fprintf(file, "%d\n", count);
for (auto &elem : numVertsInGraph)
{
fprintf(file, "%d\n", elem.first->GetArrayUniqKey().size());
fprintf(file, "%s\n", elem.first->GetArrayUniqKey().c_str());
int dimCount = elem.second.size();
fprintf(file, "%d\n", dimCount);
for (int z = 0; z < dimCount; ++z)
fprintf(file, "%d\n", elem.second[z]);
}
}
}
//load and check
bool LoadArraysFromFile(FILE *file, const SET<Array*> &currArrays, const int nextVertexNumOld)
{
bool status = true;
if (file)
{
char tmpChar;
MAP<STRING, Array*> keys;
for (auto &elem : currArrays)
keys.insert(std::make_pair(elem->GetArrayUniqKey(), elem));
fscanf(file, "%d", &nextVertexNum);
fscanf(file, "%c", &tmpChar);
if (nextVertexNumOld != nextVertexNum)
return false;
int count;
fscanf(file, "%d", &count);
fscanf(file, "%c", &tmpChar);
for (int i = 0; i < count; ++i)
{
int strLen = 0;
fscanf(file, "%d", &strLen);
fscanf(file, "%c", &tmpChar);
STRING uniqKey = "";
for (int k = 0; k < strLen; ++k)
{
char symb;
fscanf(file, "%c", &symb);
uniqKey += symb;
}
fscanf(file, "%c", &tmpChar);
int dimCount = 0;
fscanf(file, "%d", &dimCount);
fscanf(file, "%c", &tmpChar);
VECTOR<vType> tmp(dimCount);
for (int z = 0; z < dimCount; ++z)
{
fscanf(file, "%d", &(tmp[z]));
fscanf(file, "%c", &tmpChar);
}
auto found = keys.find(uniqKey);
if (found == keys.end())
{
status = false;
break;
}
else
{
numVertsInGraph.insert(std::make_pair(found->second, tmp));
arraysByName.insert(std::make_pair(found->second->GetName(), found->second));
arrays.insert(found->second);
}
}
}
else
status = false;
return status;
}
};
}
#undef MAP
#undef SET
#undef VECTOR
#undef STRING
#undef PAIR

View File

@@ -0,0 +1,648 @@
#include "../Utils/leak_detector.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <vector>
#include <set>
#include <string>
#include <algorithm>
#include <map>
#include <climits>
#include "Distribution.h"
#include "GraphCSR.h"
#include "Arrays.h"
#include "../Utils/errors.h"
#include "../Utils/utils.h"
#include "../GraphLoop/graph_loops.h"
using std::vector;
using std::set;
using std::string;
using std::get;
using std::make_pair;
using std::map;
using std::pair;
using std::tuple;
static set<DIST::Array*> arraysWithErrors;
void checkDimsSizeOfArrays(const DIST::Arrays<int> &allArrays, map<string, vector<Messages>> &allMessages,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
{
const set<DIST::Array*> &arraysBase = allArrays.GetArrays();
set<DIST::Array*> arrays;
for (auto &array : arraysBase)
getRealArrayRefs(array, array, arrays, arrayLinksByFuncCalls);
bool ok = true;
for (auto &array : arrays)
{
const vector<pair<int, int>> &sizes = array->GetSizes();
for (int k = 0; k < sizes.size(); ++k)
{
if (sizes[k].first == -1 && sizes[k].second == -1)
{
// parallize this loops with TIE regime
if (array->IsLoopArray())
continue;
if (arraysWithErrors.find(array) == arraysWithErrors.end())
{
auto declPlaces = array->GetDeclInfo();
for (auto &place : declPlaces)
{
string declF = place.first;
int declL = place.second;
char buf[256];
if (array->IsLoopArray())
sprintf(buf, "More information is required about sizes of loop '%s', decl line %d, decl file %s\n", array->GetShortName().c_str(), declL, declF.c_str());
else
sprintf(buf, "More information is required about sizes of array '%s', decl line %d, decl file %s\n", array->GetShortName().c_str(), declL, declF.c_str());
addToGlobalBufferAndPrint(buf);
arraysWithErrors.insert(array);
std::wstring bufE, bufR;
__spf_printToLongBuf(bufE, L"More information is required about sizes of array '%s'", to_wstring(array->GetShortName()).c_str());
if (array->IsLoopArray())
__spf_printToLongBuf(bufR, R149, to_wstring(array->GetShortName()).c_str());
else
__spf_printToLongBuf(bufR, R37, to_wstring(array->GetShortName()).c_str());
getObjectForFileFromMap(declF.c_str(), allMessages).push_back(Messages(ERROR, declL, bufR, bufE, 1012));
}
}
ok = false;
}
}
}
if (!ok)
{
char buf[256];
sprintf(buf, "Can not create distribution - unknown sizes\n");
addToGlobalBufferAndPrint(buf);
throw(-1);
}
}
#define WITH_REMOVE 0
static int templateCount = 0;
static DIST::Array* createTemplate(DIST::Array *distArray, DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays,
bool isMpiProgram, const map<DIST::Array*, set<DIST::Array*>>& mapOfRealRefs)
{
// find not connected dimentions and deprecate them
vector<int> vInGraph;
int err = allArrays.GetAllVertNumber(distArray, vInGraph);
if (err != 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
#if WITH_REMOVE
if (!distArray->IsLoopArray())
{
int countOfDepr = 0;
for (int z = 0; z < vInGraph.size(); ++z)
{
int count = reducedG.CountOfConnectedForArray(vInGraph[z]);
if (count <= 0)
countOfDepr++;
}
if (countOfDepr == distArray->GetDimSize())
{
for (int z = 0; z < distArray->GetDimSize(); ++z)
{
if (!distArray->IsDimMapped(z))
distArray->DeprecateDimension(z);
}
}
else
{
for (int z = 0; z < vInGraph.size(); ++z)
{
int count = reducedG.CountOfConnectedForArray(vInGraph[z]);
if (count <= 0)
distArray->DeprecateDimension(z);
}
}
}
#endif
DIST::Array *templ = new DIST::Array(*distArray);
templ->ChangeName("dvmh_temp" + std::to_string(templateCount++));
templ->SetId(0);
templ->SetTemplateFlag(true);
if (distArray->IsLoopArray())
for (int z = 0; z < templ->GetDimSize(); ++z)
templ->SetMappedDim(z);
templ->SetDimSizesToMaxMin(true);
bool ifRemAll = false;
#if WITH_REMOVE
ifRemAll = templ->RemoveUnpammedDims();
#endif
set<DIST::Array*> sameArrays;
for (auto& elem : mapOfRealRefs)
{
for (auto& array : elem.second)
{
if (array == distArray)
{
sameArrays = elem.second;
break;
}
}
if (sameArrays.size())
break;
}
for (int i = 0, templIdx = 0; i < distArray->GetDimSize(); ++i)
{
int vert = -1;
const int err = allArrays.GetVertNumber(distArray, i, vert);
if (err != 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
pair<DIST::Array*, int> result = make_pair(distArray, i);
if (!isMpiProgram)
{
set<int> wasDone;
reducedG.FindLinkWithMaxDim(vert, allArrays, result, wasDone);
}
const bool isMapped = distArray->IsDimMapped(i);
const bool isLoop = distArray->IsLoopArray();
const bool notDeprecated = isMpiProgram ? true : !distArray->IsDimDepracated(i);
if ((isMapped || isLoop) && notDeprecated)
{
AddArrayAccess(reducedG, allArrays, templ, result.first, make_pair(templIdx, result.second), 1.0, make_pair(make_pair(1, 0), make_pair(1, 0)), RR_link);
if (result.first != distArray)
templ->ExtendDimSize(templIdx, result.first->GetSizes()[result.second]);
if (isMpiProgram)
for (auto& same: sameArrays)
if (same != result.first)
AddArrayAccess(reducedG, allArrays, templ, same, make_pair(templIdx, result.second), 1.0, make_pair(make_pair(1, 0), make_pair(1, 0)), RR_link);
templIdx++;
}
#if !WITH_REMOVE
else
{
templ->ExtendDimSize(templIdx++, make_pair(1, 1));
__spf_print(1, "template %s was not added to graph!\n", templ->GetShortName().c_str());
}
#else
else
{
if (ifRemAll)
{
AddArrayAccess(reducedG, allArrays, templ, result.first, make_pair(templIdx, result.second), 1.0, make_pair(make_pair(1, 0), make_pair(1, 0)), RR_link);
templ->DeprecateDimension(i, false);
if (result.first != distArray)
templ->ExtendDimSize(templIdx, result.first->GetSizes()[result.second]);
templIdx++;
}
}
#endif
}
return templ;
}
#undef WITH_REMOVE
static vector<DIST::Array*> GetArrayWithMaximumDim(const vector<DIST::Array*> &arrays)
{
int maxDimSize = -1;
vector<DIST::Array*> retVal;
for (int i = 0; i < arrays.size(); ++i)
{
DIST::Array *tmp = arrays[i];
if (maxDimSize < tmp->GetDimSize())
{
maxDimSize = tmp->GetDimSize();
retVal.clear();
retVal.push_back(tmp);
}
else if (maxDimSize == tmp->GetDimSize())
{
const vector<pair<int, int>> &size1 = retVal.back()->GetSizes();
const vector<pair<int, int>> &size2 = tmp->GetSizes();
if (size1 == size2)
retVal.push_back(tmp);
else
{
bool ifGT = true;
for (int k = 0; k < size1.size(); ++k)
if ((size1[k].second - size1[k].first) + 1 > (size2[k].second - size2[k].first) + 1)
ifGT = false;
if (ifGT)
{
retVal.clear();
retVal.push_back(tmp);
}
}
}
}
return retVal;
}
static void convertTrees(const map<DIST::Array*, int> &treesIn, map<int, vector<DIST::Array*>> &treesOut,
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls)
{
for (auto it = treesIn.begin(); it != treesIn.end(); ++it)
{
auto foundIt = treesOut.find(it->second);
if (foundIt == treesOut.end())
foundIt = treesOut.insert(foundIt, make_pair(it->second, vector<DIST::Array*>()));
set<DIST::Array*> realRefs;
getRealArrayRefs(it->first, it->first, realRefs, arrayLinksByFuncCalls);
for (auto &array : realRefs)
foundIt->second.push_back(array);
}
}
static DIST::Array* findBestInEqual(vector<DIST::Array*> &arrays, DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays)
{
DIST::Array *retVal = NULL;
vector<vector<attrType>> coefsByDims;
for (auto &array : arrays)
{
vector<int> verts;
int err = allArrays.GetAllVertNumber(array, verts);
if (err != 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (retVal == NULL)
{
retVal = array;
for (auto &V : verts)
coefsByDims.push_back(reducedG.GetAllAttributes(V));
}
else
{
vector<vector<attrType>> toCmp;
for (auto &V : verts)
toCmp.push_back(reducedG.GetAllAttributes(V));
for (int z = 0; z < toCmp.size(); ++z)
{
if (toCmp[z].size() && coefsByDims[z].size())
{
if (toCmp[z].back().first.first > coefsByDims[z].back().first.first)
{
coefsByDims = toCmp;
retVal = array;
break;
}
}
}
}
}
return retVal;
}
static bool ArraySortFunc(DIST::Array *i, DIST::Array *j) { return (i->GetName() < j->GetName()); }
void createDistributionDirs(DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays, DataDirective &dataDirectives, map<string, vector<Messages>> &allMessages,
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, bool isMpiProgram, set<DIST::Array*> onlyThese)
{
checkDimsSizeOfArrays(allArrays, allMessages, arrayLinksByFuncCalls);
map<DIST::Array*, int> trees;
map<int, vector<DIST::Array*>> convTrees;
int countTrees = reducedG.FindAllArraysTrees(trees, allArrays);
//create one tree for all array that not found
bool hasTemplates = false;
map<DIST::Array*, set<DIST::Array*>> mapOfRealRefs;
for (auto &arrayPair : sortArraysByName(allArrays.GetArrays()))
{
DIST::Array* array = arrayPair.second;
if (onlyThese.size())
if (onlyThese.find(array) == onlyThese.end())
continue;
set<DIST::Array*> realRefs;
getRealArrayRefs(array, array, realRefs, arrayLinksByFuncCalls);
mapOfRealRefs[array] = realRefs;
for (auto &realArray : realRefs)
{
hasTemplates = hasTemplates || realArray->IsTemplate();
auto it = trees.find(realArray);
if (it == trees.end())
trees.insert(it, make_pair(realArray, ++countTrees));
}
}
vector<DIST::Array*> arraysToDist;
if (hasTemplates == false)
{
convertTrees(trees, convTrees, arrayLinksByFuncCalls);
for (auto& tree : convTrees)
{
sort(tree.second.begin(), tree.second.end(), ArraySortFunc);
vector<DIST::Array*> distrArrayV = GetArrayWithMaximumDim(tree.second);
if (distrArrayV.size() == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
DIST::Array *distrArray = findBestInEqual(distrArrayV, reducedG, allArrays);
DIST::Array *templ = createTemplate(distrArray, reducedG, allArrays, isMpiProgram, mapOfRealRefs);
checkNull(templ, convertFileName(__FILE__).c_str(), __LINE__);
arraysToDist.push_back(templ);
}
}
else
{
for (auto &array : sortArraysByName(allArrays.GetArrays()))
{
set<DIST::Array*> realRefs;
getRealArrayRefs(array.second, array.second, realRefs, arrayLinksByFuncCalls);
for (auto &realArray : sortArraysByName(realRefs))
if (realArray.second->IsTemplate())
arraysToDist.push_back(realArray.second);
}
}
sort(arraysToDist.begin(), arraysToDist.end(), ArraySortFunc);
if (arraysToDist.size())
dataDirectives.createDirstributionVariants(arraysToDist);
}
static bool createNewAlignRule(DIST::Array *alignArray, const DIST::Arrays<int> &allArrays,
vector<tuple<DIST::Array*, int, pair<int, int>>> &rules,
DataDirective &dataDirectives, map<string, vector<Messages>>& SPF_messages, bool withErrors = true)
{
DIST::Array *alignWith = NULL;
bool hasFreeDims = false;
for (int i = 0; i < rules.size(); ++i)
{
if (alignWith == NULL && get<0>(rules[i]) != NULL)
alignWith = get<0>(rules[i]);
else if (alignWith != get<0>(rules[i]) && get<0>(rules[i]) != NULL)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (get<0>(rules[i]) == NULL)
hasFreeDims = true;
}
//TODO:
if (alignWith == NULL)
{
auto allDecl = alignArray->GetDeclInfo();
for (auto& decl : allDecl)
{
std::wstring bufE, bufR;
__spf_printToLongBuf(bufE, L"Can not find align rules for array '%s'", to_wstring(alignArray->GetShortName()).c_str());
__spf_printToLongBuf(bufR, R171, to_wstring(alignArray->GetShortName()).c_str());
if (withErrors)
getObjectForFileFromMap(decl.first.c_str(), SPF_messages).push_back(Messages(ERROR, decl.second, bufR, bufE, 3020));
}
__spf_print(1, "can not find align rules for array '%s' (full name '%s')\n", alignArray->GetShortName().c_str(), alignArray->GetName().c_str());
}
if (alignWith == NULL)
return true;
//checkNull(alignWith, convertFileName(__FILE__).c_str(), __LINE__);
if (hasFreeDims)
{
set<int> usedVertDims;
vector<int> allInAlign;
allArrays.GetAllVertNumber(alignWith, allInAlign);
int countOfFree = 0;
for (int i = 0; i < rules.size(); ++i)
{
if (get<0>(rules[i]) != NULL)
usedVertDims.insert(get<1>(rules[i]));
else
countOfFree++;
}
for (int i = 0; i < allInAlign.size(); ++i)
{
if (usedVertDims.find(allInAlign[i]) != usedVertDims.end())
{
allInAlign.erase(allInAlign.begin() + i);
i--;
}
}
if (allInAlign.size() >= countOfFree)
{
int k = 0;
for (int i = 0; i < rules.size(); ++i)
{
if (get<0>(rules[i]) == NULL || alignArray->IsDimDepracated(i))
{
rules[i] = make_tuple(alignWith, allInAlign[k], make_pair(0, 0));
k++;
}
}
}
}
AlignRule newRule;
newRule.alignArray = alignArray;
newRule.alignWith = alignWith;
for (int z = 0; z < alignArray->GetDimSize(); ++z)
{
newRule.alignRule.push_back(make_pair(1, 0));
int alignToDim = -1;
int err = allArrays.GetDimNumber(alignWith, get<1>(rules[z]), alignToDim);
newRule.alignRuleWith.push_back(make_pair(alignToDim, get<2>(rules[z])));
if (get<2>(rules[z]).first == 0 && get<2>(rules[z]).second == 0)
continue;
//correct template sizes
const pair<int, int> &rule = get<2>(rules[z]);
if (alignWith->GetShortName().find("dvmh") != string::npos)
{
pair<int, int> oldSizes = alignArray->GetSizes()[z];
if (!(oldSizes.first == oldSizes.second && oldSizes.first == -1))
{
oldSizes.first = oldSizes.first * rule.first + rule.second;
oldSizes.second = oldSizes.second * rule.first + rule.second;
alignWith->ExtendDimSize(alignToDim, oldSizes);
}
}
}
dataDirectives.alignRules.push_back(newRule);
return false;
}
static string printRule(const vector<tuple<DIST::Array*, int, pair<int, int>>> &rule)
{
string print = get<0>(rule[0])->GetShortName() + " : ";
for (auto &elem : rule)
print += "(" + std::to_string(get<2>(elem).first) + "," + std::to_string(get<2>(elem).second) + ")";
return print;
}
int createAlignDirs(DIST::GraphCSR<int, double, attrType> &reducedG, const DIST::Arrays<int> &allArrays, DataDirective &dataDirectives,
const uint64_t regionId, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, map<string, vector<Messages>> &SPF_messages,
set<DIST::Array*>* canNotAlign, set<DIST::Array*> onlyThese)
{
set<DIST::Array*> distArrays;
const set<DIST::Array*> &arrays = allArrays.GetArrays();
if (dataDirectives.distrRules.size() == 0)
{
for (auto &array : arrays)
if (array->IsTemplate())
distArrays.insert(array);
if (distArrays.size() == 0)
return 1;
}
else
{
for (int i = 0; i < dataDirectives.distrRules.size(); ++i)
distArrays.insert(dataDirectives.distrRules[i].first);
}
bool repeat = true;
int countRep = 0;
while (repeat)
{
++countRep;
repeat = false;
set<pair<DIST::Array*, vector<vector<tuple<DIST::Array*, int, pair<int, int>>>>>> manyDistrRules;
int errCount = 0;
for (auto& arrayPair : sortArraysByName(arrays))
{
DIST::Array* array = arrayPair.second;
if (sharedMemoryParallelization != 0)
if (onlyThese.find(array) == onlyThese.end())
continue;
if (distArrays.find(array) != distArrays.end())
continue;
set<DIST::Array*> realArrayRefs;
getRealArrayRefs(array, array, realArrayRefs, arrayLinksByFuncCalls);
vector<vector<tuple<DIST::Array*, int, pair<int, int>>>> rules(realArrayRefs.size());
int i = 0;
bool allNonDistr = true;
bool partlyNonDistr = false;
for (auto& arrays : sortArraysByName(realArrayRefs))
{
int err = reducedG.GetAlignRuleWithTemplate(arrays.second, allArrays, rules[i], regionId);
if (err == 101)
{
reducedG.cleanCacheLinks();
dataDirectives.alignRules.clear();
repeat = true;
break;
}
bool nonDistr = arrays.second->IsNotDistribute();
allNonDistr = allNonDistr && nonDistr;
partlyNonDistr = partlyNonDistr || nonDistr;
++i;
}
if (repeat)
break;
if (allNonDistr)
continue;
if (partlyNonDistr)
{
__spf_print(1, "detected distributed and non distributed array links by function's calls for array %s\n", array->GetName().c_str());
auto allDecl = array->GetDeclInfo();
for (auto& decl : allDecl)
{
std::wstring bufE, bufR;
__spf_printToLongBuf(bufE, L"detected distributed and non distributed array links by function's calls for array '%s'\n", to_wstring(array->GetShortName()).c_str());
__spf_printToLongBuf(bufR, R140, to_wstring(array->GetShortName()).c_str());
getObjectForFileFromMap(decl.first.c_str(), SPF_messages).push_back(Messages(ERROR, decl.second, bufR, bufE, 3020));
}
for (auto& realR : realArrayRefs)
{
if (realR != array)
{
auto allDecl = realR->GetDeclInfo();
for (auto& decl : allDecl)
{
std::wstring bufE, bufR;
if (realR->IsNotDistribute())
{
__spf_printToLongBuf(bufE, L"detected non distributed array '%s' passed as a parameter to the procedure\n", to_wstring(realR->GetShortName()).c_str());
__spf_printToLongBuf(bufR, R153, to_wstring(realR->GetShortName()).c_str());
}
else
{
__spf_printToLongBuf(bufE, L"detected distributed array '%s' passed as a parameter to the procedure\n", to_wstring(realR->GetShortName()).c_str());
__spf_printToLongBuf(bufR, R141, to_wstring(realR->GetShortName()).c_str());
}
getObjectForFileFromMap(decl.first.c_str(), SPF_messages).push_back(Messages(ERROR, decl.second, bufR, bufE, 3020));
}
}
}
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
if (isAllRulesEqualWithoutArray(rules) || sharedMemoryParallelization != 0)
{
bool hasError = createNewAlignRule(array, allArrays, rules[0], dataDirectives, SPF_messages, canNotAlign == NULL);
if (hasError)
{
if (canNotAlign)
canNotAlign->insert(array);
errCount++;
}
}
else
manyDistrRules.insert(make_pair(array, rules));
}
if (errCount > 0 && canNotAlign == NULL)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (countRep > 500)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (repeat)
continue;
if (manyDistrRules.size() > 0)
{
for (auto &array : manyDistrRules)
{
__spf_print(1, "different align rules for array %s was found\n", array.first->GetName().c_str());
for (auto &rule : array.second)
__spf_print(1, " -> %s\n", printRule(rule).c_str());
std::wstring bufE, bufR;
__spf_printToLongBuf(bufE, L"different align rules for array %s were found\n", to_wstring(array.first->GetShortName()).c_str());
__spf_printToLongBuf(bufR, R142, to_wstring(array.first->GetShortName()).c_str());
for (auto &declPlace : array.first->GetDeclInfo())
getObjectForFileFromMap(declPlace.first.c_str(), SPF_messages).push_back(Messages(ERROR, declPlace.second, bufR, bufE, 3020));
}
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}
return 0;
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "../GraphLoop/graph_loops.h"
#include "../Utils/errors.h"
void createDistributionDirs(DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays,
DataDirective &dataDirectives, std::map<std::string, std::vector<Messages>> &allMessages,
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCall, bool isMpiProgram, std::set<DIST::Array*> onlyThese = std::set<DIST::Array*>());
int createAlignDirs(DIST::GraphCSR<int, double, attrType> &reducedG, const DIST::Arrays<int> &allArrays, DataDirective &dataDirectives,
const uint64_t regionId, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCall, std::map<std::string,
std::vector<Messages>> &SPF_messages, std::set<DIST::Array*>* canNotAlign = NULL, std::set<DIST::Array*> onlyThese = std::set<DIST::Array*>());
void checkDimsSizeOfArrays(const DIST::Arrays<int>& allArrays, std::map<std::string, std::vector<Messages>>& allMessages,
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);

View File

@@ -0,0 +1,122 @@
#include "../Utils/leak_detector.h"
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include "Cycle.h"
using std::vector;
using std::pair;
namespace Distribution
{
template<typename vType, typename wType, typename attrType>
void Cycle<vType, wType, attrType>::
AddArc(const pair<vType, vType> &newAcr, const wType wArc, const attrType &attrArc, const unsigned info)
{
Arcs.push_back(newAcr);
wArcs.push_back(wArc);
attrArcs.push_back(attrArc);
compressedInfo.push_back(info);
}
template<typename vType, typename wType, typename attrType>
void Cycle<vType, wType, attrType>::
AddArc(const pair<vType, vType> &newAcr, const pair<wType, attrType> &paramArc, const unsigned info)
{
AddArc(newAcr, paramArc.first, paramArc.second, info);
}
template<typename vType, typename wType, typename attrType>
void Cycle<vType, wType, attrType>::
AddArc(const vType V1, const vType V2, const pair<wType, attrType> &paramArc, const unsigned info)
{
AddArc(std::make_pair(V1, V2), paramArc.first, paramArc.second, info);
}
template<typename vType, typename wType, typename attrType>
void Cycle<vType, wType, attrType>::
AddArc(const vType V1, const vType V2, const wType wArc, const attrType &attrArc, const unsigned info)
{
AddArc(std::make_pair(V1, V2), wArc, attrArc, info);
}
template<typename vType, typename wType, typename attrType>
wType Cycle<vType, wType, attrType>::
GetCycleSum() const
{
wType sum = 0.0;
for (vType i = 0; i < (vType)Arcs.size(); ++i)
sum += wArcs[i];
return sum;
}
template<typename vType, typename wType, typename attrType>
void Cycle<vType, wType, attrType>::
SortArcs()
{
vector<pair<wType, vType>> toSort;
// sort by key
for (vType i = 0; i < (vType)wArcs.size(); ++i)
toSort.push_back(std::make_pair(wArcs[i], i));
sort(toSort.begin(), toSort.end(), comparator);
vector<pair<vType, vType>> new_Arcs(wArcs.size());
vector<wType> new_wArcs(wArcs.size());
vector<attrType> new_attrArcs(wArcs.size());
vector<unsigned> new_info(wArcs.size());
// complete sorting
for (vType i = 0; i < (vType)wArcs.size(); ++i)
{
const vType idx = toSort[i].second;
new_Arcs[i] = Arcs[idx];
new_wArcs[i] = wArcs[idx];
new_attrArcs[i] = attrArcs[idx];
if (compressedInfo.size())
new_info[i] = compressedInfo[idx];
}
attrArcs = new_attrArcs;
wArcs = new_wArcs;
Arcs = new_Arcs;
compressedInfo = new_info;
}
template<typename vType, typename wType, typename attrType>
bool Cycle<vType, wType, attrType>::
operator<(const Cycle<vType, wType, attrType> &right) const
{
return this->GetCycleSum() > right.GetCycleSum();
}
template<typename vType, typename wType, typename attrType>
void Cycle<vType, wType, attrType>::
PrintValue() const
{
printf("acrs\n");
for (int i = 0; i < Arcs.size(); ++i)
printf("%d %d\n", Arcs[i].first, Arcs[i].second);
printf("we\n");
for (int i = 0; i < wArcs.size(); ++i)
printf("%f\n", wArcs[i]);
printf("attr\n");
for (int i = 0; i < attrArcs.size(); ++i)
printf("[%d %d] [%d %d]\n", attrArcs[i].first.first, attrArcs[i].first.second, attrArcs[i].second.first, attrArcs[i].second.second);
}
template<typename vType, typename wType, typename attrType>
void Cycle<vType, wType, attrType>::
PrintArcs() const
{
for (int i = 0; i < Arcs.size(); ++i)
printf("[%d %d] ", Arcs[i].first, Arcs[i].second);
printf("\n");
}
template class Cycle<int, double, attrType>;
}

View File

@@ -0,0 +1,51 @@
#pragma once
#include <vector>
#include <algorithm>
#include "../Utils/types.h"
namespace Distribution
{
template<typename vType, typename wType, typename attrType>
class Cycle
{
private:
std::vector<std::pair<vType, vType>> Arcs;
std::vector<wType> wArcs;
std::vector<attrType> attrArcs;
std::vector<unsigned> compressedInfo;
static bool comparator(std::pair<wType, vType> left, std::pair<wType, vType> right)
{
return left.first < right.first;
}
public:
int GetNumArcs() const { return (int)Arcs.size(); }
const std::vector<std::pair<vType, vType>>& GetArcs() const { return Arcs; }
const std::vector<wType>& GetWeigthsArcs() const { return wArcs; }
const std::vector<attrType>& GetAttributesArcs() const { return attrArcs; }
void AddArc(const std::pair<vType, vType> &newAcr, const wType wArc, const attrType &attrArc, const unsigned info);
void AddArc(const std::pair<vType, vType> &newAcr, const std::pair<wType, attrType> &paramArc, const unsigned info);
void AddArc(const vType V1, const vType V2, const std::pair<wType, attrType> &paramArc, const unsigned info);
void AddArc(const vType V1, const vType V2, const wType wArc, const attrType &attrArc, const unsigned info);
wType GetCycleSum() const;
void SortArcs();
// sort as maximum
bool operator<(const Cycle<vType, wType, attrType> &right) const;
void PrintValue() const;
void PrintArcs() const;
const std::vector<unsigned>& GetShortInfo() const { return compressedInfo; }
unsigned getFullSize()
{
unsigned fullSize = 0;
fullSize += (int)Arcs.capacity() * sizeof(vType) * 2;
fullSize += (int)wArcs.capacity() * sizeof(wType);
fullSize += (int)attrArcs.capacity() * sizeof(attrArcs);
fullSize += (int)compressedInfo.capacity();
return fullSize;
}
};
}

View File

@@ -0,0 +1,629 @@
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <vector>
#include <set>
#include <tuple>
#include <string>
#include <algorithm>
#include <chrono>
#include <climits>
#include <cstring>
#if _WIN32 && NDEBUG && __BOOST
#include <boost/thread.hpp>
#endif
extern int passDone;
using std::pair;
using std::set;
using std::make_pair;
using std::string;
using std::wstring;
using std::tuple;
using std::vector;
using namespace std::chrono;
#include "GraphCSR.h"
#include "Arrays.h"
#include "Array.h"
#include "Distribution.h"
#include "../Utils/utils.h"
#include "../Utils/errors.h"
#include "../Utils/types.h"
#include "../Distribution/Cycle.h"
#include "../VisualizerCalls/get_information.h"
#include "../VisualizerCalls/SendMessage.h"
extern int keepFiles;
#define ERROR_CHECK(err) do { if (err != 0) return err; } while(0)
#define FIRST(x) get<0>(x)
#define SECOND(x) get<1>(x)
#define THIRD(x) get<2>(x)
namespace Distribution
{
//fix attributes: pair< pair<int, int>, pair<int, int> >
template<typename attrType>
attrType shiftByDiffInArc(const attrType& arcAttr)
{
pair<int, int> left = arcAttr.first;
pair<int, int> right = arcAttr.second;
if (left.first == right.first)
{
if (left.second == right.second)
left.second = right.second = 0;
else if (left.second != 0 && right.second != 0)
{
const int diffZeroL = abs(left.second - 0);
const int diffZeroR = abs(right.second - 0);
if (diffZeroL < diffZeroR)
{
if (left.second > 0)
{
left.second -= diffZeroL;
right.second -= diffZeroL;
}
else
{
left.second += diffZeroL;
right.second += diffZeroL;
}
}
else
{
if (right.second > 0)
{
left.second -= diffZeroR;
right.second -= diffZeroR;
}
else
{
left.second += diffZeroR;
right.second += diffZeroR;
}
}
}
}
return make_pair(left, right);
}
template<typename attrType>
attrType inverseArcByShifts(const attrType& arcAttr)
{
pair<int, int> left = arcAttr.first;
pair<int, int> right = arcAttr.second;
if (left.first == right.first)
{
if (left.second < 0 && right.second < 0)
;
else if (left.second < 0)
{
std::swap(left.second, right.second);
right.second = -right.second;
}
else if (right.second < 0)
{
std::swap(left.second, right.second);
left.second = -left.second;
}
}
return make_pair(left, right);
}
template<typename vType, typename wType, typename attrType>
int AddArrayAccess(GraphCSR<vType, wType, attrType> &G, Arrays<vType> &allArrays,
Array *arr1, Array *arr2, pair<int, int> arc, wType arcWeight, const attrType &arcAttr,
const uint8_t linkType)
{
int err = 0;
allArrays.AddArrayToGraph(arr1);
allArrays.AddArrayToGraph(arr2);
vType V1, V2;
ERROR_CHECK(allArrays.GetVertNumber(arr1, arc.first, V1));
ERROR_CHECK(allArrays.GetVertNumber(arr2, arc.second, V2));
G.AddToGraph(V1, V2, arcWeight, shiftByDiffInArc(arcAttr), linkType);
return err;
}
template<typename vType, typename wType, typename attrType>
static int GetIdxOfNextCycle(const vector<tuple<vType, vType, attrType>> &localDelArcs,
const vector<Cycle<vType, wType, attrType>> &cycles,
const vector<pair<int, int>> &indexOfConflict,
const int idxStart = 0)
{
int idx = -1;
for (int i = idxStart; i < (int)indexOfConflict.size(); ++i)
{
const Cycle<vType, wType, attrType> &currCycle = cycles[indexOfConflict[i].first];
if (localDelArcs.size() == 0)
{
idx = i;
break;
}
else
{
const vector<pair<vType, vType>> &arcs = currCycle.GetArcs();
const vector<attrType> &attributes = currCycle.GetAttributesArcs();
bool same = false;
for (int k = 0; k < (int)arcs.size(); ++k)
{
const tuple<vType, vType, attrType> toCheck = make_tuple(arcs[k].first, arcs[k].second, attributes[k]);
const tuple<vType, vType, attrType> toCheckRev = make_tuple(arcs[k].second, arcs[k].first, make_pair(attributes[k].second, attributes[k].first));
same = false;
for (int m = 0; m < (int)localDelArcs.size(); ++m)
{
if (toCheck == localDelArcs[m] || toCheckRev == localDelArcs[m])
{
same = true;
break;
}
}
if (same)
break;
}
if (same)
continue;
else
{
idx = i;
break;
}
}
}
return idx;
}
template<typename vType, typename wType, typename attrType>
static int GetIdxOfNextCycle(const unsigned *fastCache, const vector<unsigned> &localDelArcsShort,
const vector<Cycle<vType, wType, attrType>> &cycles,
const vector<pair<int, int>> &indexOfConflict,
const int idxStart = 0)
{
int idx = -1;
const pair<int, int> *data = indexOfConflict.data();
for (int i = idxStart; i < (int)indexOfConflict.size(); ++i)
{
const Cycle<vType, wType, attrType> &currCycle = cycles[data[i].first];
if (localDelArcsShort.size() == 0)
{
idx = i;
break;
}
else
{
const vector<unsigned> &shortInfo = currCycle.GetShortInfo();
bool same = false;
for (int k = 0; k < (int)shortInfo.size(); ++k)
{
if (fastCache[shortInfo[k]] == 1)
{
same = true;
break;
}
}
if (same)
continue;
else
{
idx = i;
break;
}
}
}
return idx;
}
static inline bool checkGraphTrue(const int startV, const int realV, const GraphCSR<int, double, attrType> &G)
{
return true;
}
static inline bool checkGraph(const int startV, const int realV, const GraphCSR<int, double, attrType> &G)
{
return realV == G.CountOfConnected(startV);
}
template<typename vType, typename wType, typename attrType, bool check(const int startV, const int realV, const GraphCSR<vType, wType, attrType> &G)>
static void FindBestSequenceForDelArcs(double &globalSum, vector<tuple<vType, vType, attrType>> &globalDelArcs,
const double localSum, vector<tuple<vType, vType, attrType>> &localDelArcs,
vector<unsigned> &localDelArcsShort,
unsigned *fastCache,
const vector<Cycle<vType, wType, attrType>> &cycles, const vector<pair<int, int>> &indexOfConflict,
const int lastIndexOfConflict, const int countInTree,
const GraphCSR<vType, wType, attrType> &graph)
{
int nextConflict = GetIdxOfNextCycle(fastCache, localDelArcsShort, cycles, indexOfConflict, lastIndexOfConflict + 1);
if (nextConflict == -1)
{
globalSum = localSum;
globalDelArcs = localDelArcs;
//char buf[256];
//sprintf(buf, " global sum = %f, last idx of conflict %d\n", globalSum, lastIndexOfConflict);
printf("SAPFOR: global sum = %f, last idx of conflict %d\n", globalSum, lastIndexOfConflict);
//addToGlobalBufferAndPrint(buf);
createNeededException();
}
else
{
const Cycle<vType, wType, attrType> &conflicCycle = cycles[indexOfConflict[nextConflict].first];
const vector<pair<vType, vType>> &arcs = conflicCycle.GetArcs();
const vector<unsigned> &shortInfo = conflicCycle.GetShortInfo();
const vector<wType> &weights = conflicCycle.GetWeigthsArcs();
const vector<attrType> &attributes = conflicCycle.GetAttributesArcs();
for (int i = 0; i < (int)arcs.size(); ++i)
{
const pair<vType, vType> &currArc = arcs[i];
const wType currW = weights[i];
const attrType &currAttr = attributes[i];
if (!check(currArc.first, countInTree, graph))
continue;
else
{
if (localSum + currW < globalSum)
{
localDelArcs.push_back(make_tuple(currArc.first, currArc.second, currAttr));
localDelArcsShort.push_back(shortInfo[i]);
fastCache[shortInfo[i]] = 1;
FindBestSequenceForDelArcs
<vType, wType, attrType, check>
(globalSum, globalDelArcs, localSum + currW, localDelArcs, localDelArcsShort, fastCache, cycles, indexOfConflict, nextConflict, countInTree, graph);
fastCache[shortInfo[i]] = 0;
localDelArcs.pop_back();
localDelArcsShort.pop_back();
}
else
{
createNeededException();
break;
}
}
}
}
}
template<typename vType, typename wType, typename attrType>
static void CountConflictVarints(int64_t &countVars,
vector<unsigned> &localDelArcsShort, unsigned *fastCache,
const vector<Cycle<vType, wType, attrType>> &cycles, const vector<pair<int, int>> &indexOfConflict,
const int lastIndexOfConflict)
{
int nextConflict = GetIdxOfNextCycle(fastCache, localDelArcsShort, cycles, indexOfConflict, lastIndexOfConflict + 1);
if (nextConflict == -1)
{
countVars++;
return;
}
else
{
const Cycle<vType, wType, attrType> &conflicCycle = cycles[indexOfConflict[nextConflict].first];
const vector<unsigned> &shortInfo = conflicCycle.GetShortInfo();
for (int i = 0; i < (int)shortInfo.size(); ++i)
{
localDelArcsShort.push_back(shortInfo[i]);
fastCache[shortInfo[i]] = 1;
CountConflictVarints(countVars, localDelArcsShort, fastCache, cycles, indexOfConflict, nextConflict);
fastCache[shortInfo[i]] = 0;
localDelArcsShort.pop_back();
}
}
}
#define DEGUB_DEL_ALL_CYCLES 0
template<typename vType, typename wType, typename attrType>
static void FindNonConflictDelArcs(vector<tuple<vType, vType, attrType>> &delArcs, const vector<Cycle<vType, wType, attrType>> &cycles)
{
vector<pair<int, int>> idxOfLoops(cycles.size());
// fill indexs for all lopps for using 'GetIdxOfNextCycle' procedure
for (int i = 0; i < (int)cycles.size(); ++i)
#if !DEGUB_DEL_ALL_CYCLES
idxOfLoops[i] = std::make_pair(i, 0);
#else
{
const std::vector<pair<vType, vType>> &arcs = cycles[i].GetArcs();
const std::vector<attrType> &attrs = cycles[i].GetAttributesArcs();
for (int i = 0; i < arcs.size(); ++i)
delArcs.push_back(std::make_tuple(arcs[i].first, arcs[i].second, attrs[i]));
}
#endif
#if !DEGUB_DEL_ALL_CYCLES
int idxNext = -1;
do
{
idxNext = GetIdxOfNextCycle(delArcs, cycles, idxOfLoops, idxNext + 1);
if (idxNext != -1)
{
std::pair<vType, vType> arc = cycles[idxNext].GetArcs()[0];
attrType attr = cycles[idxNext].GetAttributesArcs()[0];
delArcs.push_back(std::make_tuple(arc.first, arc.second, attr));
}
} while (idxNext != -1);
#endif
}
#undef DEGUB_DEL_ALL_CYCLES
template<typename vType, typename wType, typename attrType>
static pair<bool, double> CreateOptimalAlignementTree(GraphCSR<vType, wType, attrType> &G, const Arrays<vType> &allArrays,
vector<tuple<vType, vType, attrType>> &toDelArcs, bool needPrint = true, bool useSavedQ = false)
{
double globalSum = 0;
bool allOnlySecondType = true;
vector<vType> trees;
vector<vector<vType>> vertByTrees;
set<vType> unqieTrees = G.FindTrees(trees, vertByTrees);
__spf_print(needPrint, " GRAPH size: |V| = %d, |E| = %d\n", G.GetNumberOfV(), G.GetNumberOfE() / 2);
__spf_print(needPrint, " TREES count %d\n", (int)unqieTrees.size());
vector<unsigned char> tmp;
for (int z = 0; z < vertByTrees.size(); ++z)
if (vertByTrees[z].size())
__spf_print(needPrint, " TREES %d: V = %d, E = %d\n", z, (int)vertByTrees[z].size(), G.MakeConnected(vertByTrees[z][0], tmp).second);
else
__spf_print(needPrint, " TREES %d: V = %d, E = %d\n", z, 0, 0);
toDelArcs = G.CreateMaximumSpanningTree();
return make_pair(allOnlySecondType, globalSum);
// OLD ALGORITHM, THIS IS unreachable code !!
vector<vector<Cycle<vType, wType, attrType>>> AllCycles;
G.GetAllSimpleLoops(AllCycles, needPrint, useSavedQ);
toDelArcs.clear();
for (int k = 0; k < AllCycles.size(); ++k)
{
unsigned maxElem = 0;
bool onlySecondConflictType = true;
for (auto &elem : AllCycles[k])
for (auto &cycleShortInfo : elem.GetShortInfo())
maxElem = std::max(maxElem, cycleShortInfo);
if (maxElem != 0 && needPrint)
printf(" SAPFOR: max elem for cache %lld, in MB: %f\n", maxElem, maxElem / 1024. / 1024. * sizeof(unsigned));
unsigned *fastCache = new unsigned[maxElem];
memset(fastCache, 0, sizeof(unsigned) * maxElem);
char buf[256];
if (needPrint)
{
sprintf(buf, " PROF: [%d TREE]:\n", k);
addToGlobalBufferAndPrint(buf);
}
double globalSumLocal = (double)INT32_MAX;
vector<pair<vType, vType>> indexOfConflict;
vector<Cycle<vType, wType, attrType>> &cycles = AllCycles[k];
vector<tuple<vType, vType, attrType>> localDelArcs;
vector<unsigned> localDelArcShort;
G.SortLoopsBySize(cycles, needPrint);
G.SortLoopsByWeight(cycles, needPrint);
for (int i = 0; i < (int)cycles.size(); ++i)
cycles[i].SortArcs();
int countConflicts = G.GetConflictCycles(cycles, allArrays, indexOfConflict, needPrint);
if (needPrint)
{
sprintf(buf, " num of conflict cycles %d\n", countConflicts);
printf("SAPFOR: num of conflict cycles %d\n", countConflicts);
addToGlobalBufferAndPrint(buf);
}
if (countConflicts != 0)
{
int typeConflict[2] = { 0, 0 };
for (int i = 0; i < indexOfConflict.size(); ++i)
typeConflict[indexOfConflict[i].second]++;
if (needPrint)
{
sprintf(buf, " num of type1 = %d, type2 = %d\n", typeConflict[0], typeConflict[1]);
printf("SAPFOR: num of type1 = %d, type2 = %d\n", typeConflict[0], typeConflict[1]);
addToGlobalBufferAndPrint(buf);
}
if (typeConflict[0])
{
onlySecondConflictType = false;
allOnlySecondType = false;
}
}
if (needPrint)
{
#if _WIN32
wstring treeM = L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> " + std::to_wstring(k + 1) + L"/" + std::to_wstring(AllCycles.size());
#else
wstring treeM = L"conflict resolution, processing group " + std::to_wstring(k + 1) + L"/" + std::to_wstring(AllCycles.size());
#endif
sendMessage_2lvl(treeM);
}
auto timeR = steady_clock::now();
if (countConflicts != 0)
{
const int countInTree = G.CountOfConnected(cycles[indexOfConflict[0].first].GetArcs()[0].first);
const int lastIndexOfConflict = -1;
if (needPrint)
printf("SAPFOR: before del %d\n", countInTree);
/*int64_t countVars = 0;
CountConflictVarints(countVars, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict);
printf("SAPFOR: count of vars %lld\n", countVars);*/
if (onlySecondConflictType)
FindBestSequenceForDelArcs
<vType, wType, attrType, checkGraph>
(globalSumLocal, toDelArcs, 0, localDelArcs, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict, countInTree, G);
else
FindBestSequenceForDelArcs
<vType, wType, attrType, checkGraphTrue>
(globalSumLocal, toDelArcs, 0, localDelArcs, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict, countInTree, G);
if (needPrint)
{
auto tmpReducedG = G;
tmpReducedG.RemovedEdges(toDelArcs, allArrays);
if (needPrint)
printf("SAPFOR: after del %d\n", tmpReducedG.CountOfConnected(cycles[indexOfConflict[0].first].GetArcs()[0].first));
}
globalSum += globalSumLocal;
}
if (needPrint)
{
sprintf(buf, "PROF: FindBestSequenceForDelArcs: %f sec\n", (duration_cast<duration<double>>(steady_clock::now() - timeR)).count());
printf("SAPFOR: time of FindBestSequenceForDelArcs %f sec\n", (duration_cast<duration<double>>(steady_clock::now() - timeR)).count());
addToGlobalBufferAndPrint(buf);
}
timeR = steady_clock::now();
FindNonConflictDelArcs(toDelArcs, cycles);
if (needPrint)
{
sprintf(buf, "PROF: FindNonConflictDelArcs %f\n", (duration_cast<duration<double>>(steady_clock::now() - timeR)).count());
addToGlobalBufferAndPrint(buf);
}
delete []fastCache;
}
if (needPrint)
sendMessage_2lvl(L"");
return make_pair(allOnlySecondType, globalSum);
}
template<typename vType, typename wType, typename attrType>
void createOptimalDistribution(GraphCSR<vType, wType, attrType> &G, GraphCSR<vType, wType, attrType> &reducedG,
const Arrays<vType> &allArrays, const uint64_t regionNum, bool onlyGraph)
{
vector<tuple<int, int, attrType>> toDelArcs;
if (G.GetNumberOfE() == 0)
return;
double globalSum = 0;
string FullName = "_graph_full_reg" + std::to_string(regionNum) + ".txt";
string ReducedName = "_graph_reduced_reg" + std::to_string(regionNum) + ".txt";
//__spf_print(1, "flag keepFiles %d, flag onlyGraph %d\n", keepFiles, onlyGraph);
if (keepFiles)
{
if (!onlyGraph)
G.CreateGraphWiz(FullName.c_str(), toDelArcs, allArrays, false);
else
G.CreateGraphWiz(FullName.c_str(), vector<tuple<int, int, attrType>>(), allArrays, true);
}
if (!onlyGraph)
{
G.HighlightLinks();
//old simple algorithm
//G.RemoveMultipleArcsByWeights();
//new algorithm with optimal strategy
G.RemoveMultipleArcsOptimal();
pair<bool, double> retVal = CreateOptimalAlignementTree(G, allArrays, toDelArcs);
globalSum = retVal.second;
bool onlySecondType = retVal.first;
reducedG = G;
reducedG.RemovedEdges(toDelArcs, allArrays);
double maxWeight = reducedG.CalculateSumOfWeights() + 1;
//try to resolve conflicts of 1 type
const set<Array*> &arrays = allArrays.GetArrays();
vector<Array*> arraysV;
arraysV.assign(arrays.begin(), arrays.end());
for (int z = 0; z < arraysV.size(); ++z)
{
const DIST::Array *array = arraysV[z];
#ifdef _WIN32
wstring treeM = L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> " + std::to_wstring(z + 1) + L"/" + std::to_wstring(arrays.size());
#else
wstring treeM = L"conflict resolution, processing array " + std::to_wstring(z + 1) + L"/" + std::to_wstring(arrays.size());
#endif
sendMessage_2lvl(treeM);
vector<vType> verts;
if (array->GetDimSize() == 1)
continue;
int err = allArrays.GetAllVertNumber(array, verts);
if (err != 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
attrType tmpPair = make_pair(make_pair(1, 0), make_pair(1, 0));
for (int i = 0; i < verts.size(); ++i)
{
for (int j = i + 1; j < verts.size(); ++j)
{
GraphCSR<vType, wType, attrType> findConflict(reducedG);
findConflict.AddToGraph(verts[i], verts[j], maxWeight, tmpPair, WW_link);
vector<tuple<int, int, attrType>> toDelArcsLocal;
globalSum = CreateOptimalAlignementTree(findConflict, allArrays, toDelArcsLocal, false, true).second;
if (toDelArcsLocal.size() != 0)
reducedG.RemovedEdges(toDelArcsLocal, allArrays);
}
}
}
sendMessage_2lvl(L"");
}
else
{
reducedG = G;
reducedG.RemoveMultipleArcsByWeights();
}
if (keepFiles)
reducedG.CreateGraphWiz(ReducedName.c_str(), vector<tuple<int, int, attrType>>(), allArrays, true);
}
template void createOptimalDistribution(GraphCSR<int, double, attrType> &G, GraphCSR<int, double, attrType> &reducedG, const Arrays<int> &allArrays, const uint64_t regionNum, bool onlyGraph);
template int AddArrayAccess(GraphCSR<int, double, attrType> &G, Arrays<int> &allArrays, Array *arr1, Array *arr2, pair<int, int> arc, double arcWeight, const attrType &arcAttr, const uint8_t linkType);
template attrType shiftByDiffInArc(const attrType& arcAttr);
template attrType inverseArcByShifts(const attrType& arcAttr);
}
#undef ERROR_CHECK
#undef FIRST
#undef SECOND
#undef THIRD

View File

@@ -0,0 +1,28 @@
#pragma once
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include "GraphCSR.h"
#include "Arrays.h"
#include "Array.h"
namespace DIST = Distribution;
namespace Distribution
{
template<typename attrType>
attrType shiftByDiffInArc(const attrType& arcAttr);
template<typename attrType>
attrType inverseArcByShifts(const attrType& arcAttr);
template<typename vType, typename wType, typename attrType>
int AddArrayAccess(GraphCSR<vType, wType, attrType> &G, Arrays<vType> &allArrays,
Array *arr1, Array *arr2, std::pair<int, int> arc, wType arcWeight,
const attrType &arcAttr, const uint8_t linkType);
template<typename vType, typename wType, typename attrType>
void createOptimalDistribution(GraphCSR<vType, wType, attrType> &G, GraphCSR<vType, wType, attrType> &reducedG,
const Arrays<vType> &allArrays, const uint64_t regionNum, bool onlyGraph);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
#pragma once
#include <string>
#include <vector>
#include <set>
#include <map>
#include "Array.h"
#include "DvmhDirectiveBase.h"
#include "../Utils/AstWrapper.h"
#include "../Utils/types.h"
#include "../Utils/utils.h"
extern int sharedMemoryParallelization;
struct LoopGraph;
namespace Distribution
{
template<typename vType, typename wType, typename attrType> class GraphCSR;
template<typename vType> class Arrays;
}
namespace DIST = Distribution;
struct AlignRule : public AlignRuleBase
{
public:
Statement* GenRule(File *file, const int variant) const;
};
struct DistrVariant : public DistrVariantBase
{
public:
DistrVariant(const std::vector<dist> &distRule) : DistrVariantBase(distRule) { }
void GenRule(File *file, Expression *arrayRef, const std::vector<int> &newOrder) const;
std::vector<Expression*> GenRuleSt(File *file, const std::vector<int> &newOrder) const;
};
struct DataDirective : Directive
{
public:
std::vector<AlignRule> alignRules;
std::vector<std::pair<DIST::Array*, std::vector<DistrVariant>>> distrRules;
public:
std::vector<std::pair<DIST::Array*, std::vector<DistrVariant>>> GetDistrRules() const { return distrRules; }
void createDirstributionVariants(const std::vector<DIST::Array*> &arraysToDist);
std::vector<std::string> GenRule(const std::vector<int> &rules) const;
std::vector<std::string> GenAlignsRules() const;
std::vector<AlignRule> GenAlignsRules(void*) { return alignRules; }
std::vector<Statement*> GenRule(File *file, const std::vector<int> &rules, const int variant) const;
std::vector<std::vector<dist>> GenRule(const std::vector<int> &rules, int) const;
std::vector<Statement*> GenAlignsRules(File *file, const int variant) const;
void UpdateLinks(const std::map<DIST::Array*, DIST::Array*> &oldNewArrays)
{
for (int i = 0; i < distrRules.size(); ++i)
distrRules[i].first = oldNewArrays.find(distrRules[i].first)->second;
}
~DataDirective()
{
for (auto &elem : distrRules)
{
if (elem.first && elem.first->IsTemplate())
{
delete elem.first;
elem.first = NULL;
}
}
}
};
struct CreatedDirective : Directive
{
std::string data;
std::vector<Expression*> sageData;
explicit CreatedDirective(const std::string& data, const std::vector<Expression*>& sageData) :
data(data), sageData(sageData)
{ }
explicit CreatedDirective(const std::string& data, const std::vector<Expression*>& sageData, int line) :
data(data), sageData(sageData)
{
this->line = line;
}
};
struct ParallelDirective : Directive
{
public:
std::vector<std::string> parallel;
// tuple of <varName, A, B> on A*x + B
std::vector<std::pair<std::string, std::pair<int, int>>> on;
DIST::Array *arrayRef; // template
DIST::Array *arrayRef2;// main array in loop
std::vector<std::pair<std::string, std::pair<int, int>>> on2;
std::string cloneOfTemplate; // if loop has realigns before
std::set<Symbol*> privates;
// origin_Name uniqName bounds
std::vector<std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>> shadowRenew;
std::vector<std::vector<std::pair<int, int>>> shadowRenewShifts;
// origin_Name uniqName bounds
std::vector<std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>> across;
std::vector<std::vector<std::pair<int, int>>> acrossShifts;
// origin_Name uniqName expression
std::map<std::pair<std::pair<std::string, std::string>, std::string>, Expression*> remoteAccess;
std::map<std::string, std::set<std::string>> reduction;
std::map<std::string, std::set<std::tuple<std::string, std::string, int>>> reductionLoc;
public:
ParallelDirective() : arrayRef(NULL), arrayRef2(NULL) { }
ParallelDirective(const ParallelDirective &copyFrom) : Directive(copyFrom)
{
parallel = copyFrom.parallel;
on = copyFrom.on;
on2 = copyFrom.on2;
arrayRef = copyFrom.arrayRef;
arrayRef2 = copyFrom.arrayRef2;
privates = copyFrom.privates;
shadowRenew = copyFrom.shadowRenew;
shadowRenewShifts = copyFrom.shadowRenewShifts;
across = copyFrom.across;
acrossShifts = copyFrom.acrossShifts;
remoteAccess = copyFrom.remoteAccess;
reduction = copyFrom.reduction;
reductionLoc = copyFrom.reductionLoc;
cloneOfTemplate = copyFrom.cloneOfTemplate;
}
//for F_LANG;
Directive*
genDirective(File *file, const std::vector<std::pair<DIST::Array*, const DistrVariant*>> &distribution,
LoopGraph* currLoop,
DIST::GraphCSR<int, double, attrType> &reducedG,
DIST::Arrays<int> &allArrays,
const uint64_t regionId,
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls);
friend ParallelDirective* operator+(const ParallelDirective &first, const ParallelDirective &second);
~ParallelDirective()
{
parallel.clear();
on.clear();
privates.clear();
shadowRenew.clear();
across.clear();
acrossShifts.clear();
reduction.clear();
reductionLoc.clear();
remoteAccess.clear();
}
private:
std::string genBounds(std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>> &shadowOp,
std::vector<std::pair<int, int>> &shadowOpShift,
DIST::GraphCSR<int, double, attrType> &reducedG,
DIST::Arrays<int> &allArrays, DIST::Array* shadowArray,
std::map<DIST::Array*, std::vector<ArrayOp>>& remoteRegularReads,
const std::map<DIST::Array*, std::pair<std::vector<ArrayOp>, std::vector<bool>>> &readOps,
const bool isAcross, const uint64_t regionId,
const std::vector<std::pair<DIST::Array*, const DistrVariant*>> &distribution,
std::set<DIST::Array*> &arraysInAcross,
std::vector<std::map<std::pair<int, int>, int>> &shiftsByAccess,
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls) const;
std::string genBoundsNoDist(std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>& shadowOp,
std::vector<std::pair<int, int>>& shadowOpShift,
DIST::Array* currArray,
const std::map<DIST::Array*, std::pair<std::vector<ArrayOp>, std::vector<bool>>>& readOps,
std::set<DIST::Array*>& arraysInAcross,
std::vector<std::map<std::pair<int, int>, int>>& shiftsByAccess,
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls) const;
};
std::string genStringExpr(const std::string &letter, const std::pair<int, int> expr);
std::pair<std::string, std::string> convertDigitToPositive(const int digit);

View File

@@ -0,0 +1,811 @@
#include "../Utils/leak_detector.h"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <algorithm>
#include "DvmhDirective.h"
#include "../Distribution/Array.h"
#include "../Distribution/Arrays.h"
#include "../Distribution/GraphCSR.h"
#include "../Utils/errors.h"
#include "../Utils/utils.h"
#include "../GraphCall/graph_calls_func.h"
using std::vector;
using std::tuple;
using std::get;
using std::string;
using std::pair;
using std::set;
using std::map;
using std::set_union;
using std::make_pair;
using std::min;
using std::max;
template<typename setT>
static void uniteSets(const set<setT> &first, const set<setT> &second, set<setT> &result)
{
vector<setT> unitedVector(first.size() + second.size());
auto it = set_union(first.begin(), first.end(), second.begin(), second.end(), unitedVector.begin());
unitedVector.resize(it - unitedVector.begin());
for (int i = 0; i < (int)unitedVector.size(); ++i)
result.insert(unitedVector[i]);
}
template<typename keyT, typename valT>
static void uniteSets(const map<keyT, valT> &first, const map<keyT, valT> &second, map<keyT, valT> &result)
{
vector<pair<keyT, valT>> unitedVector(first.size() + second.size());
auto it = set_union(first.begin(), first.end(), second.begin(), second.end(), unitedVector.begin());
unitedVector.resize(it - unitedVector.begin());
for (int i = 0; i < (int)unitedVector.size(); ++i)
result.insert(unitedVector[i]);
}
template<typename keyT, typename valT>
static void uniteReduction(const map<keyT, valT> &first, const map<keyT, valT> &second, map<keyT, valT> &result)
{
auto itF = first.begin();
for (auto &redList : result)
{
auto itFound = second.find(redList.first);
if (itFound != second.end())
uniteSets(itF->second, itFound->second, redList.second);
++itF;
}
for (auto redList : second)
{
auto itFound = result.find(redList.first);
if (itFound == result.end())
result.insert(itFound, redList);
}
}
template<typename vTuples>
static vTuples uniteOnRules(const vTuples &first, const vTuples &second)
{
vTuples result(first.size());
for (int i = 0; i < (int)first.size(); ++i)
{
bool firstStar = first[i].first == "*";
bool secondStar = second[i].first == "*";
if (firstStar && secondStar)
result[i].first = "*";
else if (firstStar)
result[i] = second[i];
else
result[i] = first[i];
}
return result;
}
template<typename vTuples>
static bool hasConflictUniteOnRules(const vTuples& first, const vTuples& second)
{
if (first.size() != second.size())
return true;
for (int i = 0; i < (int)first.size(); ++i)
{
bool firstStar = first[i].first == "*";
bool secondStar = second[i].first == "*";
if (!firstStar && !secondStar)
return true;
}
return false;
}
ParallelDirective* operator+(const ParallelDirective &left, const ParallelDirective &right)
{
const ParallelDirective *first = &left;
const ParallelDirective *second = &right;
ParallelDirective *result = NULL;
checkNull(first, convertFileName(__FILE__).c_str(), __LINE__);
checkNull(second, convertFileName(__FILE__).c_str(), __LINE__);
bool condition = first->arrayRef == second->arrayRef;
if (sharedMemoryParallelization)
condition = !hasConflictUniteOnRules(first->on, second->on) && !hasConflictUniteOnRules(first->on2, second->on2);
if (condition)
{
if (first->on.size() != second->on.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
result = new ParallelDirective();
result->langType = first->langType;
result->file = first->file;
result->line = first->line;
result->col = first->col;
result->arrayRef = first->arrayRef;
result->arrayRef2 = first->arrayRef2;
result->parallel = vector<string>(first->parallel.size() + second->parallel.size());
result->on = vector<pair<string, pair<int, int>>>(first->on.size());
for (int i = 0; i < (int)first->parallel.size(); ++i)
result->parallel[i] = first->parallel[i];
for (int i = 0; i < (int)second->parallel.size(); ++i)
result->parallel[i + first->parallel.size()] = second->parallel[i];
result->on = uniteOnRules(first->on, second->on);
result->on2 = uniteOnRules(first->on2, second->on2);
uniteVectors(first->across, second->across, result->across);
uniteVectors(first->shadowRenew, second->shadowRenew, result->shadowRenew);
uniteSets(first->privates, second->privates, result->privates);
uniteSets(first->remoteAccess, second->remoteAccess, result->remoteAccess);
result->reduction = first->reduction;
result->reductionLoc = first->reductionLoc;
uniteReduction(first->reduction, second->reduction, result->reduction);
uniteReduction(first->reductionLoc, second->reductionLoc, result->reductionLoc);
}
else
result = new ParallelDirective(left);
return result;
}
static inline int findRule(const int alingDim, const vector<tuple<DIST::Array*, int, pair<int, int>>> &rule, pair<int, pair<int, int>> &retVal)
{
for (int i = 0; i < rule.size(); ++i)
{
if (get<1>(rule[i]) == alingDim)
{
retVal = make_pair(alingDim, get<2>(rule[i]));
return 0;
}
}
return -1;
}
static inline bool isNonDistributedDim(const vector<tuple<DIST::Array*, int, pair<int, int>>> &ruleForOn,
const vector<tuple<DIST::Array*, int, pair<int, int>>> &ruleForShadow,
const int dimN,
const vector<pair<DIST::Array*, const DistrVariant*>> &distribution,
const vector<pair<string, pair<int, int>>> &parallelOnRule)
{
if (ruleForShadow.size() <= dimN)
return false;
if (get<0>(ruleForShadow[dimN]) == NULL)
return true;
//check for distributed in declaration or in redistr. rules
const tuple<DIST::Array*, int, pair<int, int>> &toCheck = ruleForShadow[dimN];
const int dimInTepml = get<1>(toCheck);
for (auto &templ : distribution)
{
if (templ.first == get<0>(toCheck))
{
if (templ.second->distRule[dimInTepml] == NONE)
return true;
}
}
//check for distributed in loop
if (dimInTepml >= 0 && dimInTepml < parallelOnRule.size())
if (parallelOnRule[dimInTepml].first == "*")
return true;
return false;
}
vector<tuple<DIST::Array*, int, pair<int, int>>>
getAlignRuleWithTemplate(DIST::Array *array, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
DIST::GraphCSR<int, double, attrType> &reducedG, const DIST::Arrays<int> &allArrays,
const uint64_t regionId)
{
vector<tuple<DIST::Array*, int, pair<int, int>>> retVal;
set<DIST::Array*> realRefs;
getRealArrayRefs(array, array, realRefs, arrayLinksByFuncCalls);
vector<vector<tuple<DIST::Array*, int, pair<int, int>>>> allRuleForShadow(realRefs.size());
int idx = 0;
for (auto &array : realRefs)
reducedG.GetAlignRuleWithTemplate(array, allArrays, allRuleForShadow[idx++], regionId);
if (realRefs.size() == 1)
retVal = allRuleForShadow[0];
else
{
bool eq = isAllRulesEqual(allRuleForShadow);
if (eq == false)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
else
retVal = allRuleForShadow[0];
}
return retVal;
}
bool needCorner(const DIST::Array* currArray, const vector<map<pair<int, int>, int>>& shiftsByAccess, const vector<vector<pair<int, int>>>& refsInLoop)
{
for (auto& access : refsInLoop)
{
int countOfShadows = 0;
if (access.size() < currArray->GetDimSize())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int i = 0; i < currArray->GetDimSize(); ++i)
{
const pair<int, int>& coef = access[i];
auto it = shiftsByAccess[i].find(coef);
if (it != shiftsByAccess[i].end())
if (it->second != 0)
countOfShadows++;
}
if (countOfShadows > 1)
return true;
}
return false;
}
static inline string calculateShifts(DIST::GraphCSR<int, double, attrType> &reducedG,
const DIST::Arrays<int> &allArrays,
DIST::Array *arrayRef, DIST::Array *calcForArray,
pair<pair<string, string>, vector<pair<int, int>>> &coeffs,
vector<pair<int, int>> &shifts,
vector<map<pair<int, int>, int>> &shiftsByAccess,
map<DIST::Array*, vector<ArrayOp>>& remoteRegularReads,
const vector<pair<string, pair<int, int>>> baseOnRule,
const vector<pair<string, pair<int, int>>> parallelOnRule,
const map<DIST::Array*, pair<vector<ArrayOp>, vector<bool>>> &readOps, const bool isAcross,
const vector<pair<DIST::Array*, const DistrVariant*>> &distribution,
const uint64_t regionId,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
{
vector<tuple<DIST::Array*, int, pair<int, int>>> ruleForOn, ruleForShadow;
if (!sharedMemoryParallelization)
{
ruleForOn = getAlignRuleWithTemplate(arrayRef, arrayLinksByFuncCalls, reducedG, allArrays, regionId);
ruleForShadow = getAlignRuleWithTemplate(calcForArray, arrayLinksByFuncCalls, reducedG, allArrays, regionId);
}
string out = "";
// check for distributed and not mapped dims -> zero them out ('coeffs.second')
set<DIST::Array*> refs;
getRealArrayRefs(calcForArray, calcForArray, refs, arrayLinksByFuncCalls);
//TODO: need to correct errors
/*if (!sharedMemoryParallelization)
{
for (auto& array : refs)
{
DIST::Array* tmpl = array->GetTemplateArray(regionId);
checkNull(tmpl, convertFileName(__FILE__).c_str(), __LINE__);
auto align = array->GetLinksWithTemplate(regionId);
bool found = false;
for (auto& t : distribution)
{
if (t.first == tmpl)
{
found = true;
for (int aDim = 0; aDim < align.size(); ++aDim)
{
int link = align[aDim];
if (link != -1)
{
int tLink = link;
if (!arrayRef->IsTemplate())
{
auto alignMain = arrayRef->GetLinksWithTemplate(regionId);
for (int z = 0; z < alignMain.size(); ++z)
if (alignMain[z] == tLink)
tLink = z;
}
if (t.second->distRule[link] == dist::BLOCK && baseOnRule[aDim].first == "*")
{
for (int z = 0; z < coeffs.second.size(); ++z)
coeffs.second[z].first = coeffs.second[z].second = 0;
return out;
}
}
}
}
}
if (!found)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}*/
const pair<vector<ArrayOp>, vector<bool>> *currReadOp = NULL;
auto readIt = readOps.find(calcForArray);
if (readIt != readOps.end())
currReadOp = &(readIt->second);
if(!sharedMemoryParallelization)
{
findAndReplaceDimentions(ruleForOn, allArrays);
findAndReplaceDimentions(ruleForShadow, allArrays);
}
const int len = (int)coeffs.second.size();
vector<pair<int, int>> shift(len);
bool allZero = true;
for (int k = 0; k < len; ++k)
{
shiftsByAccess.push_back(map<pair<int, int>, int>());
shift[k].first = shift[k].second = 0;
if (k != 0)
out += ",";
char buf[256];
// calculate correct shifts from readOp info
if (currReadOp)
{
// no unrecognized read operations
if (currReadOp->second[k] == false)
{
if (sharedMemoryParallelization)
{
for (auto& coefs : currReadOp->first[k].coefficients)
{
auto currAccess = coefs.first;
const int currShift = coefs.first.second;
auto itFound = shiftsByAccess[k].find(currAccess);
if (itFound == shiftsByAccess[k].end())
itFound = shiftsByAccess[k].insert(itFound, make_pair(currAccess, currShift));
}
}
else if (get<0>(ruleForShadow[k]) != NULL)
{
const pair<int, int> currRuleShadow = get<2>(ruleForShadow[k]);
pair<int, pair<int, int>> currRuleOn;
int err = findRule(get<1>(ruleForShadow[k]), ruleForOn, currRuleOn);
if (err == 0)
{
if (currRuleOn.first >= parallelOnRule.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const pair<int, int> loopRule = DIST::Fx(parallelOnRule[currRuleOn.first].second, currRuleOn.second);
if (loopRule.first != 0)
{
int minShift = 9999999;
int maxShift = -9999999;
for (auto &coefs : currReadOp->first[k].coefficients)
{
auto currAccess = coefs.first;
auto result = DIST::Fx(currAccess, currRuleShadow);
if (result.first == loopRule.first)
{
const int absShift = abs(result.second - loopRule.second);
const int signShift = (result.second - loopRule.second) > 0 ? 1 : -1;
const int currShift = signShift * (absShift / currRuleShadow.first + ((absShift % currRuleShadow.first) != 0));
minShift = std::min(minShift, currShift);
maxShift = std::max(maxShift, currShift);
auto itFound = shiftsByAccess[k].find(currAccess);
if (itFound == shiftsByAccess[k].end())
itFound = shiftsByAccess[k].insert(itFound, make_pair(currAccess, currShift));
}
else // remote_access
{
auto it = remoteRegularReads.find(calcForArray);
if (it == remoteRegularReads.end())
it = remoteRegularReads.insert(it, make_pair(calcForArray, vector<ArrayOp>(calcForArray->GetDimSize())));
it->second[k].coefficients.insert(coefs);
}
}
// inconsistent -> may be remote will add later...
// or SINGLE position
if (minShift == 9999999 && maxShift == -9999999)
minShift = maxShift = 0;
if (minShift == maxShift)
{
if (minShift == 0)
{
if (parallelOnRule[currRuleOn.first].first != "SINGLE")
{
shift[k].first = -coeffs.second[k].first;
shift[k].second = -coeffs.second[k].second;
}
}
else
{
shift[k].first = -minShift;
shift[k].second = minShift;
if (shift[k].first > 0 && shift[k].second < 0)
shift[k].second = 0;
else if (shift[k].first < 0 && shift[k].second > 0)
shift[k].first = 0;
shift[k].first -= coeffs.second[k].first;
shift[k].second -= coeffs.second[k].second;
}
}
else if (currReadOp->first[k].coefficients.size() > 0)
{
if (minShift > 0 && maxShift > 0)
{
shift[k].first = 0;
shift[k].second = std::abs(maxShift) - coeffs.second[k].second;
}
else if (minShift < 0 && maxShift < 0)
{
shift[k].first = std::abs(minShift) - coeffs.second[k].first;
shift[k].second = 0;
}
else
{
shift[k].first = std::abs(minShift) - coeffs.second[k].first;
shift[k].second = std::abs(maxShift) - coeffs.second[k].second;
}
}
}
}
}
}
}
if(!sharedMemoryParallelization)
{
if (coeffs.second[k].first + shift[k].first < 0)
shift[k].first = -coeffs.second[k].first;
if (coeffs.second[k].second + shift[k].second < 0)
shift[k].second = -coeffs.second[k].second;
if (isAcross)
{
if (coeffs.second[k] == make_pair(0, 0))
shift[k] = make_pair(0, 0);
}
else if (isNonDistributedDim(ruleForOn, ruleForShadow, k, distribution, parallelOnRule))
{
shift[k].first = -coeffs.second[k].first;
shift[k].second = -coeffs.second[k].second;
shiftsByAccess[k].clear();
}
}
sprintf(buf, "%d:%d", coeffs.second[k].first + shift[k].first, coeffs.second[k].second + shift[k].second);
shifts[k] = shift[k];
if (coeffs.second[k].first + shift[k].first != 0 || coeffs.second[k].second + shift[k].second != 0)
allZero = false;
out += buf;
}
if (allZero)
return "";
else
return out;
}
string ParallelDirective::genBounds(pair<pair<string, string>, vector<pair<int, int>>> &shadowOp,
vector<pair<int, int>> &shadowOpShift,
DIST::GraphCSR<int, double, attrType> &reducedG,
DIST::Arrays<int> &allArrays, DIST::Array* shadowArray,
map<DIST::Array*, vector<ArrayOp>>& remoteRegularReads,
const map<DIST::Array*, pair<vector<ArrayOp>, vector<bool>>> &readOps,
const bool isAcross,
const uint64_t regionId,
const vector<pair<DIST::Array*, const DistrVariant*>> &distribution,
set<DIST::Array*> &arraysInAcross,
vector<map<pair<int, int>, int>> &shiftsByAccess,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls) const
{
checkNull(shadowArray, convertFileName(__FILE__).c_str(), __LINE__);
auto on_ext = on;
if(!sharedMemoryParallelization)
{
//replace to template align ::on
if (arrayRef->IsTemplate() == false)
{
vector<tuple<DIST::Array*, int, pair<int, int>>> ruleForRef =
getAlignRuleWithTemplate(arrayRef, arrayLinksByFuncCalls, reducedG, allArrays, regionId);
findAndReplaceDimentions(ruleForRef, allArrays);
on_ext.clear();
for (int i = 0; i < ruleForRef.size(); ++i)
{
if (get<0>(ruleForRef[i]))
{
on_ext.resize(get<0>(ruleForRef[i])->GetDimSize());
break;
}
}
if (on_ext.size() == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
std::fill(on_ext.begin(), on_ext.end(), make_pair("*", make_pair(0, 0)));
for (int i = 0; i < ruleForRef.size(); ++i)
if (get<0>(ruleForRef[i]))
on_ext[get<1>(ruleForRef[i])] = on[i];
}
//replace single dim to key word 'SINGLE'
for (int i = 0; i < on_ext.size(); ++i)
{
if (on_ext[i].first != "*")
{
if (std::find(parallel.begin(), parallel.end(), on_ext[i].first) == parallel.end())
on_ext[i].first = "SINGLE";
}
}
}
string ret = "";
if (isAcross)
{
arraysInAcross.insert(shadowArray);
ret = calculateShifts(reducedG, allArrays, arrayRef, shadowArray, shadowOp, shadowOpShift, shiftsByAccess, remoteRegularReads, on, on_ext, readOps, isAcross, distribution, regionId, arrayLinksByFuncCalls);
}
else
{
if (arraysInAcross.find(shadowArray) == arraysInAcross.end())
ret = calculateShifts(reducedG, allArrays, arrayRef, shadowArray, shadowOp, shadowOpShift, shiftsByAccess, remoteRegularReads, on, on_ext, readOps, isAcross, distribution, regionId, arrayLinksByFuncCalls);
}
return ret;
}
static void genVariants(const int dimNum, vector<dist> &currDist, std::vector<DistrVariant> &currdist)
{
if (dimNum == 1)
{
DistrVariant var1(currDist);
var1.distRule.push_back(dist::NONE);
DistrVariant var2(currDist);
var2.distRule.push_back(dist::BLOCK);
currdist.push_back(var1);
currdist.push_back(var2);
}
else
{
vector<dist> next(currDist);
next.push_back(dist::NONE);
genVariants(dimNum - 1, next, currdist);
next.back() = dist::BLOCK;
genVariants(dimNum - 1, next, currdist);
}
}
void DataDirective::createDirstributionVariants(const vector<DIST::Array*> &arraysToDist)
{
for (int i = 0; i < arraysToDist.size(); ++i)
{
vector<DistrVariant> currdist;
vector<dist> currDist;
genVariants(arraysToDist[i]->GetDimSize(), currDist, currdist);
//deprecate by dims
for (auto &variant : currdist)
{
for (int z = 0; z < arraysToDist[i]->GetDimSize(); ++z)
if (arraysToDist[i]->IsDimDepracated(z) || !arraysToDist[i]->IsDimMapped(z))
variant.distRule[z] = dist::NONE;
}
distrRules.push_back(make_pair(arraysToDist[i], currdist));
}
}
string DistrVariantBase::GenRuleBase(const vector<int> &newOrder) const
{
string retVal = "";
retVal += "(";
for (int i = 0; i < distRule.size(); ++i)
{
if (newOrder.size() == 0)
{
if (distRule[i] == dist::NONE)
retVal += "*";
else if (distRule[i] == dist::BLOCK)
retVal += "BLOCK";
}
else
{
if (distRule[newOrder[i]] == dist::NONE)
retVal += "*";
else if (distRule[newOrder[i]] == dist::BLOCK)
retVal += "BLOCK";
}
if (i != distRule.size() - 1)
retVal += ",";
}
retVal += ")";
return retVal;
}
vector<string> DataDirective::GenRule(const vector<int> &rules) const
{
vector<string> retVal;
if (distrRules.size() < rules.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int i = 0; i < rules.size(); ++i)
{
if (rules[i] < distrRules[i].second.size())
{
string tmp = distrRules[i].first->GetShortName();
tmp += distrRules[i].second[rules[i]].GenRuleBase(distrRules[i].first->GetNewTemplateDimsOrder());
retVal.push_back(tmp);
}
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
return retVal;
}
vector<vector<dist>> DataDirective::GenRule(const vector<int> &rules, int) const
{
vector<vector<dist>> retVal;
if (distrRules.size() < rules.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int i = 0; i < rules.size(); ++i)
{
if (rules[i] < distrRules[i].second.size())
retVal.push_back(distrRules[i].second[rules[i]].distRule);
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
return retVal;
}
vector<string> DataDirective::GenAlignsRules() const
{
vector<string> retVal;
for (int i = 0; i < alignRules.size(); ++i)
retVal.push_back(alignRules[i].GenRuleBase());
return retVal;
}
string AlignRuleBase::GenRuleBase() const
{
string retVal = "";
retVal += "ALIGN " + alignArray->GetShortName() + "(";
for (int i = 0; i < alignRule.size(); ++i)
{
retVal += genStringExpr(alignNames[i], alignRule[i]);
if (i != alignRule.size() - 1)
retVal += ",";
}
retVal += ") WITH " + alignWith->GetShortName() + "(";
vector<string> alignEachDim(alignWith->GetDimSize());
for (int i = 0; i < alignWith->GetDimSize(); ++i)
alignEachDim[i] = "*";
for (int i = 0; i < alignRuleWith.size(); ++i)
if (alignRuleWith[i].first != -1)
alignEachDim[alignRuleWith[i].first] = genStringExpr(alignNames[i], alignRuleWith[i].second);
auto newOrder = alignWith->GetNewTemplateDimsOrder();
if (newOrder.size() != 0)
{
vector<string> alignEachDimNew(alignEachDim);
for (int z = 0; z < newOrder.size(); ++z)
alignEachDim[z] = alignEachDimNew[newOrder[z]];
}
for (int i = 0; i < alignWith->GetDimSize(); ++i)
{
retVal += alignEachDim[i];
if (i != alignWith->GetDimSize() - 1)
retVal += ",";
}
retVal += ")";
return retVal;
}
string AlignRuleBase::toString()
{
string retVal = "";
if (alignArray)
retVal += "#" + std::to_string((long long)alignArray);
else
retVal += "#-1";
if (alignWith)
retVal += "#" + std::to_string((long long)alignWith);
else
retVal += "#-1";
retVal += "#" + std::to_string(alignRule.size());
for (int i = 0; i < alignRule.size(); ++i)
retVal += "#" + std::to_string(alignRule[i].first) + "#" + std::to_string(alignRule[i].second);
retVal += "#" + std::to_string(alignRuleWith.size());
for (int i = 0; i < alignRuleWith.size(); ++i)
retVal += "#" + std::to_string(alignRuleWith[i].first)
+ "#" + std::to_string(alignRuleWith[i].second.first)
+ "#" + std::to_string(alignRuleWith[i].second.second);
return retVal;
}
pair<string, string> convertDigitToPositive(const int digit)
{
char buf[16];
string sign = " + ";
if (digit < 0)
{
sign = " - ";
int val = -digit;
sprintf(buf, "%d", val);
}
else
sprintf(buf, "%d", digit);
return make_pair(sign, buf);
}
string genStringExpr(const string &letter, const pair<int, int> expr)
{
string retVal = "";
if (expr.first == 0 && expr.second == 0)
retVal = "*";
else if (expr.second == 0)
{
if (expr.first == 1)
retVal = letter;
else
{
pair<string, string> digit2 = convertDigitToPositive(expr.first);
if (digit2.first == " - ")
digit2.second = "(-" + digit2.second + ")";
retVal = digit2.second + string(" * ") + letter;
}
}
else
{
pair<string, string> digit1 = convertDigitToPositive(expr.second);
if (expr.first == 1)
retVal = letter + digit1.first + digit1.second;
else
{
pair<string, string> digit2 = convertDigitToPositive(expr.first);
if (digit2.first == " - ")
digit2.second = "(-" + digit2.second + ")";
retVal = digit2.second + string(" * ") + letter + digit1.first + digit1.second;
}
}
return retVal;
}
const std::vector<std::string> AlignRuleBase::alignNames = { "iEX1", "iEX2", "iEX3", "iEX4", "iEX5", "iEX6", "iEX7" };

View File

@@ -0,0 +1,70 @@
#pragma once
#include <vector>
#include <string>
typedef enum lang : int { LANG_C, LANG_F } language;
typedef enum dist : int { BLOCK, NONE } distType;
typedef std::pair<std::pair<int, int>, std::pair<int, int>> attrType;
namespace Distribution
{
class Array;
}
namespace DIST = Distribution;
struct Directive
{
lang langType;
std::string file;
int line;
int col;
Directive ()
{
#if __SPF
langType = LANG_F;
#else
langType = LANG_C;
#endif
file = "";
line = 0;
col = 0;
}
Directive(const Directive &dir)
{
langType = dir.langType;
file = dir.file;
line = dir.line;
col = dir.col;
}
};
struct AlignRuleBase
{
public:
static const std::vector<std::string> alignNames;
public:
std::string GenRuleBase() const;
std::string toString();
public:
DIST::Array *alignArray;
DIST::Array *alignWith;
std::vector<std::pair<int, int>> alignRule;
std::vector<std::pair<int, std::pair<int, int>>> alignRuleWith;
};
struct DistrVariantBase
{
public:
std::vector<dist> distRule;
public:
DistrVariantBase(const std::vector<dist> &distRule) : distRule(distRule) { }
std::string GenRuleBase(const std::vector<int> &newOrder) const;
};
bool needCorner(const DIST::Array* currArray, const std::vector<std::map<std::pair<int, int>, int>>& shiftsByAccess, const std::vector<std::vector<std::pair<int, int>>>& refsInLoop);

View File

@@ -0,0 +1,12 @@
#pragma once
#include <vector>
#include <string>
#include <set>
#include "dvm.h"
#include "../Utils/types.h"
SgExpression* createAndSetNext(const int side, const int variant, SgExpression *p);
std::vector<SgExpression*> genSubscripts(const std::vector<std::pair<int, int>> &shadowRenew, const std::vector<std::pair<int, int>> &shadowRenewShifts);
std::pair<SgExpression*, SgExpression*> genShadowSpec(SgFile *file, const std::pair<std::string, const std::vector<std::pair<int, int>>> &shadowSpecs);
void correctShadowSpec(SgExpression *spec, const std::vector<std::pair<int, int>> &shadowSpecs);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,171 @@
#pragma once
#include <vector>
#include <map>
#include <set>
#include <tuple>
#include "../Utils/RationalNum.h"
typedef enum links { RR_link, WR_link, WW_link } LinkType;
#define MAX_LOOP_DIM 8
#define MAX_CHAIN_LEN 8
namespace Distribution
{
class Array;
template<typename vType> class Arrays;
template<typename vType, typename wType, typename attrType> class Cycle;
template<typename vType, typename wType, typename attrType>
class GraphCSR
{
private:
vType numVerts;
vType numEdges;
vType lastNumOfV;
std::vector<vType> neighbors;
std::vector<vType> edges;
std::vector<wType> weights;
std::vector<uint8_t> linkType;
std::vector<attrType> attributes;
std::vector<vType> localIdx;
std::vector<vType> globalIdx;
//for finding
std::vector<vType> color;
vType *activeV;
vType *activeE;
std::pair<wType, attrType> *activeArcs;
uint64_t usedMem;
std::vector<std::pair<int, int>> treesQuality;
int activeCounter;
vType findFrom;
bool hardLinksWasUp;
int maxChainLen;
int maxLoopDim;
uint64_t maxAvailMemory;
std::map<vType, std::map<vType, std::tuple<int, Array*, std::pair<RationalNum, RationalNum>>>> cacheLinks;
int countRequestsToAdd, countMissToAdd;
private:
GraphCSR(const std::vector<vType> &neighbors, const std::vector<vType> &edges,
const std::vector<wType> &weights, const std::vector<vType> &localIdx,
const std::vector<vType> &globalIdx, const std::vector<attrType> &attributes,
const std::vector<uint8_t> &linkType, const bool hardLinksWasUp) :
neighbors(neighbors), edges(edges), weights(weights), localIdx(localIdx),
globalIdx(globalIdx), attributes(attributes), linkType(linkType), hardLinksWasUp(hardLinksWasUp)
{
numVerts = (int)neighbors.size() - 1;
numEdges = (int)edges.size();
}
vType GetLocalVNum(const vType &V, bool &ifNew);
void AddEdgeToGraph(const vType &V1, const vType &V2, const wType &W, const attrType &attr, const bool &ifNew, const uint8_t linkType);
void IncreaseWeight(const int &idx, const int &idxRev, const wType &W);
int CheckExist(const vType &V1, const vType &V2, const attrType &attr, const bool &ifNew, const uint8_t &linkType);
//old algorithm without sort in the fly
//TODO: need to update
void FindLoop(std::vector<Cycle<vType, wType, attrType>> &cycles, const vType V, const vType VPrev);
void FindLoop(std::vector<std::map<std::vector<unsigned>, Cycle<vType, wType, attrType>>> &cycles, const vType V, const vType VPrev, const std::vector<vType> &numbers);
void RemoveDuplicates(std::vector<Cycle<vType, wType, attrType>> &cycles);
bool findLink(const vType v1, std::pair<int, int> &inGraphAttr1, const vType v2, std::pair<int, int> &inGraphAttr2);
std::pair<RationalNum, RationalNum> findLinkWithTempate2(const vType v1, int &templV, Array *&templ, const Arrays<vType> &allArrays, std::set<vType> wasDone);
int findDimNumLink(const vType v, const Array *to, const Arrays<vType> &allArrays, std::set<vType> &wasDone) const;
bool checkFirstCoefOfNode(vType node);
bool getOptimalBoundsForNode(vType nodeFrom, vType nodeTo, int &needBound, std::pair<int, int> &bounds);
bool hasLinkWithTempate(const vType root, const Arrays<vType> &allArrays, bool, int newValue = 0);
public:
GraphCSR()
{
ClearGraphCSR();
}
GraphCSR(const GraphCSR &G) : GraphCSR(G.neighbors, G.edges, G.weights, G.localIdx, G.globalIdx, G.attributes, G.linkType, G.hardLinksWasUp)
{
this->lastNumOfV = G.lastNumOfV;
this->maxLoopDim = G.maxLoopDim;
this->maxChainLen = G.maxChainLen;
this->maxAvailMemory = G.maxAvailMemory;
this->countRequestsToAdd = G.countRequestsToAdd;
this->countMissToAdd = G.countMissToAdd;
this->treesQuality = G.treesQuality;
}
void cleanCacheLinks() { cacheLinks.clear(); }
void ClearGraphCSR()
{
lastNumOfV = numVerts = numEdges = 0;
hardLinksWasUp = false;
neighbors.resize(0);
edges.resize(0);
weights.resize(0);
linkType.resize(0);
localIdx.resize(0);
globalIdx.resize(0);
attributes.resize(0);
treesQuality.resize(0);
maxLoopDim = MAX_LOOP_DIM;
maxChainLen = MAX_CHAIN_LEN;
maxAvailMemory = 0;
countRequestsToAdd = 0;
countMissToAdd = 0;
}
std::set<vType> FindTrees(std::vector<vType> &inTree, std::vector<std::vector<vType>> &vertByTrees);
bool SaveGraphToFile(FILE *file);
bool LoadGraphFromFile(FILE *file);
int AddToGraph(const vType &V1, const vType &V2, const wType &W, const attrType &attr, const uint8_t linkType);
void GetAllSimpleLoops(std::vector<std::vector<Cycle<vType, wType, attrType>>> &cycles, bool needPrint, bool useSavedQ);
int SortLoopsBySize(std::vector<Cycle<vType, wType, attrType>> &cycles, bool needPrint);
int SortLoopsByWeight(std::vector<Cycle<vType, wType, attrType>> &cycles, bool needPrint);
int GetConflictCycles(const std::vector<Cycle<vType, wType, attrType>> &cycles, const Arrays<vType> &allArrays, std::vector<std::pair<int, int>> &indexOfConflict, bool needPrint);
void RemoveMultipleArcsByWeights();
void RemoveMultipleArcsOptimal();
void RemoveVerticesByWeight();
int CreateGraphWiz(const char *fileName, const std::vector<std::tuple<vType, vType, attrType>> &toDelArcs, const Arrays<vType> &allArrays, const bool onlyTree);
void RemovedEdges(const std::vector<std::tuple<vType, vType, attrType>> &toDelArcs, const Arrays<vType> &allArrays);
void HighlightLinks();
int GetAlignRuleForArray(Array *inputArray, const Arrays<vType> &allArrays, std::vector<std::vector<std::tuple<Array*, vType, attrType>>> &assignedArrays);
int GetAlignRuleWithTemplate(Array *inputArray, const Arrays<vType> &allArrays, std::vector<std::tuple<Array*, vType, std::pair<int, int>>> &rules, const uint64_t regionId);
void FindLinksBetweenArrays(const Arrays<vType> &allArrays, const Array *from, const Array *to, std::vector<int> &links) const;
void FindLinkWithMaxDim(const vType from, const Arrays<vType> &allArrays, std::pair<Array*, int> &result, std::set<int> &wasDone);
int FindAllArraysTrees(std::map<Array*, int> &trees, const Arrays<vType> &allArrays);
vType GetNumberOfV() const { return numVerts; }
vType GetNumberOfE() const { return numEdges; }
void SetMaxLoopDim(const int newMaxLoopDim) { maxLoopDim = newMaxLoopDim; }
void SetMaxChainLen(const int newMaxChainLen) { maxChainLen = newMaxChainLen; }
int GetMaxLoopDim() const { return maxLoopDim; }
int GetMaxChainLen() const { return maxChainLen; }
void SetMaxAvailMemory(const uint64_t memSize) { maxAvailMemory = memSize; }
void ChangeQuality(const int newMaxLoopDim, const int newMaxChainLen) { SetMaxLoopDim(newMaxLoopDim); SetMaxChainLen(newMaxChainLen); }
int getCountOfReq() const { return countRequestsToAdd; }
int getCountOfMiss() const { return countMissToAdd; }
std::vector<attrType> GetAllAttributes(const int vert) const;
int CountOfConnected(const vType startV) const;
int CountOfConnectedForArray(const vType startV) const;
std::vector<std::tuple<vType, vType, attrType>> CreateMaximumSpanningTree();
std::pair<int, int> MakeConnected(const vType startV, std::vector<unsigned char> &inSet) const;
double CalculateSumOfWeights() const
{
double ret = 0;
for (int z = 0; z < weights.size(); ++z)
ret += weights[z] / 2.0;
return ret;
}
void RemoveAllEdgesFromGraph(const std::map<Array*, std::vector<std::pair<int, int>>>& toDel, const Arrays<vType>& allArrays);
};
std::pair<int, int> Fx(const std::pair<int, int> &x, const std::pair<int, int> &F);
}

View File

@@ -0,0 +1,38 @@
#include "leak_detector.h"
#include "DvmhRegion.h"
DvmhRegion::DvmhRegion(LoopGraph *loopNode, const std::string &fun_name) : fun_name(fun_name)
{
loops.push_back(loopNode);
}
SgStatement* DvmhRegion::getFirstSt() const
{
if (loops.size() < 1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return loops.front()->loop->GetOriginal();
}
SgStatement* DvmhRegion::getLastSt() const
{
if (loops.size() < 1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return loops.back()->loop->GetOriginal()->lastNodeOfStmt();
}
void DvmhRegion::append(DvmhRegion& region)
{
for (auto& loop : region.getLoops())
addLoop(loop);
}
int DvmhRegion::getLineForSort() const
{
if (loops.size() == 0)
return -1;
int line = loops[0]->lineNum;
if (line < 0)
line = loops[0]->altLineNum;
return line;
}

View File

@@ -0,0 +1,28 @@
#pragma once
#include "../GraphLoop/graph_loops_func.h"
#include <string>
class DvmhRegion
{
private:
std::vector<LoopGraph*> loops;
std::string fun_name;
public:
DvmhRegion() { }
DvmhRegion(LoopGraph *loopNode, const std::string &fun_name);
SgStatement* getFirstSt() const;
SgStatement* getLastSt() const;
void addLoop(LoopGraph* newLoop) { loops.push_back(newLoop); }
const std::string& getFunName() const { return fun_name; }
void setFunName(const std::string& newName) { fun_name = newName; }
const std::vector<LoopGraph*>& getLoops() const { return loops; }
std::string getFileName() const { return getFirstSt()->fileName(); }
void append(DvmhRegion& region);
int getLineForSort() const;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,120 @@
#pragma once
#include "../GraphCall/graph_calls_func.h"
#include "../GraphLoop/graph_loops_func.h"
#include "../ExpressionTransform/expr_transform.h"
#include "../ParallelizationRegions/ParRegions.h"
#include "../Utils/SgUtils.h"
#include "ReadWriteAnalyzer.h"
#include "DvmhRegion.h"
typedef std::set<DIST::Array* > ArraySet;
struct ReadWrite
{
ArraySet read;
ArraySet write;
};
typedef std::map<int, ReadWrite> UsageByLine;
typedef std::map<std::string, UsageByLine> UsageByFile;
class DvmhRegionInserter
{
// input data
SgFile *file;
std::map<int, LoopGraph*> loopGraphMap;
const std::vector<LoopGraph*> loopGraph;
const std::map<std::string, FuncInfo*> allFunctions;
const std::vector<FuncInfo*> funcsForFile;
bool isMpiProgram;
ReadWriteAnalyzer& rw_analyzer;
std::map<FuncInfo*, std::set<LoopGraph*>> parallel_functions;
std::set<DIST::Array*> writesToArraysInParallelLoops;
std::set<DIST::Array*> usedArraysInParallelLoops;
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls;
// operating data
std::vector<DvmhRegion*> regions;
// region directives
void findEdgesForRegions(const std::vector<LoopGraph*>&);
bool hasLimitsToDvmhParallel(const LoopGraph*) const;
void insertRegionDirectives();
// actual directives
ArraySet symbs_to_arrs(std::set<SgSymbol*>) const;
ArraySet get_used_arrs(SgStatement* st, int usage_type) const;
ArraySet get_used_arrs_for_block(SgStatement* st, int usage_type) const;
SgStatement* processSt(SgStatement *st, const std::vector<ParallelRegion*>* regs);
void insertActualDirective(SgStatement*, const ArraySet&, int, bool, const std::set<std::string>* = NULL);
void parFuncsInNode(LoopGraph *loop, bool isParallel);
bool isLoopParallel(const LoopGraph *loop) const;
std::vector<SgExpression*> getArrayList(Statement* start, Statement* end, bool left = false) const;
ArraySet applyUseFilter(const ArraySet& block, const std::set<DIST::Array*>& filter) const;
ArraySet excludePrivates(const ArraySet& block) const;
ArraySet excludeRemotes(const ArraySet& block, SgStatement* remoteDir) const;
void insertForProcCall(SgStatement* st, bool& skipGetActualIfProcCall, bool& skipActualIfProcCall);
public:
explicit DvmhRegionInserter(
SgFile* curFile,
const std::vector<LoopGraph*>& curLoopGraph,
ReadWriteAnalyzer& rws,
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
const std::map<std::string, FuncInfo*>& allFunctions,
const std::vector<FuncInfo*>& funcsForFile,
bool mpi_program
) : file(curFile), loopGraph(curLoopGraph), rw_analyzer(rws), arrayLinksByFuncCalls(arrayLinksByFuncCalls), allFunctions(allFunctions), funcsForFile(funcsForFile), isMpiProgram(mpi_program)
{
if (loopGraph.size())
createMapLoopGraph(loopGraph, loopGraphMap);
}
void insertDirectives(const std::vector<ParallelRegion*>* regs = NULL);
void insertActualDirectives(const std::vector<ParallelRegion*>* regs);
void updateParallelFunctions(const std::map<std::string, std::vector<LoopGraph*>>& loopGraphs);
void createInterfaceBlockForParallelFunctions(bool onlyRoutine = true);
void removePrivatesFromParallelLoops();
void addPrivatesToParallelLoops();
void addUsedArrays(std::set<DIST::Array*>& arrays);
void addUsedWriteArrays(std::set<DIST::Array*>& arrays);
void updateUsedArrays(const std::set<DIST::Array*>& used, const std::set<DIST::Array*>& usedForWrite)
{
ArraySet newSet = usedForWrite;
for (auto& elem : usedForWrite)
getRealArrayRefs(elem, elem, newSet, arrayLinksByFuncCalls);
writesToArraysInParallelLoops = newSet;
newSet = used;
for (auto& elem : used)
getRealArrayRefs(elem, elem, newSet, arrayLinksByFuncCalls);
usedArraysInParallelLoops = newSet;
}
const std::set<FuncInfo*> getParallelFunctions() const {
std::set<FuncInfo*> retVal;
for (auto& elem : parallel_functions)
retVal.insert(elem.first);
return retVal;
}
static void createInterfaceBlockForOutCall(FuncInfo* func, FuncInfo* callFrom);
static void createInterfaceBlockForOutCalls(FuncInfo* func);
~DvmhRegionInserter()
{
for (auto& reg : regions)
delete reg;
}
};
int insertDvmhRegions(SgProject& project, int files, const std::vector<ParallelRegion*>& parallelRegions,
std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo,
std::map<std::string, std::vector<LoopGraph*>> loopGraph,
ReadWriteAnalyzer& rw_analyzer,
std::map<std::string, std::vector<Messages>>& SPF_messages,
const std::map<DIST::Array*, std::set<DIST::Array*>> arrayLinksByFuncCalls);

View File

@@ -0,0 +1,72 @@
#include "leak_detector.h"
#include "LoopChecker.h"
using namespace std;
void LoopChecker::updateLoopGraph(const map<string, FuncInfo*> &allFuncs)
{
for (auto &loopNode : loopGraph)
updateLoopNode(loopNode, allFuncs);
}
LoopCheckResults LoopChecker::updateLoopNode(LoopGraph *loop, const map<string, FuncInfo*> &allFuncs)
{
LoopCheckResults loopChecks = checkLoopForPurenessAndIO(loop, allFuncs);
bool hasImpureCalls = loopChecks.hasImpureCalls;
bool usesIO = loopChecks.usesIO;
if (loopChecks.linesOfIO.size() && usesIO)
for (auto& elem : loopChecks.linesOfIO)
loop->linesOfIO.insert(elem);
for (auto &nestedLoop : loop->children)
{
loopChecks = updateLoopNode(nestedLoop, allFuncs);
hasImpureCalls |= loopChecks.hasImpureCalls;
usesIO |= loopChecks.usesIO;
}
loop->hasNonPureProcedures |= hasImpureCalls;
loop->hasPrints |= usesIO;
return LoopCheckResults(loop->hasPrints, loop->hasNonPureProcedures);
}
// checks loop node itself, doesn't check its children
LoopCheckResults LoopChecker::checkLoopForPurenessAndIO(const LoopGraph *loopNode, const map<string, FuncInfo*> &allFuncs) const
{
LoopCheckResults loopCheckResults;
for (auto &nameAndLineOfFuncCalled : loopNode->calls)
{
FuncInfo *calledFuncInfo = NULL;
auto it = allFuncs.find(nameAndLineOfFuncCalled.first);
if (it != allFuncs.end())
calledFuncInfo = it->second;
if (!calledFuncInfo)
{
if (isIntrinsicFunctionName(nameAndLineOfFuncCalled.first.c_str()))
continue;
else
{ // if funcInfo was not found assume func to be impure
loopCheckResults.hasImpureCalls = true;
loopCheckResults.usesIO = true;
loopCheckResults.linesOfIO.push_back(nameAndLineOfFuncCalled.second);
}
continue;
}
if (!calledFuncInfo->isPure)
loopCheckResults.hasImpureCalls = true;
if (calledFuncInfo->usesIO())
{
loopCheckResults.usesIO = true;
loopCheckResults.linesOfIO.push_back(nameAndLineOfFuncCalled.second);
}
}
return loopCheckResults;
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include "../GraphLoop/graph_loops_func.h"
#include "../GraphCall/graph_calls_func.h"
#include <vector>
#include <string>
#include <map>
struct LoopCheckResults
{
bool usesIO;
bool hasImpureCalls;
std::vector<int> linesOfIO;
LoopCheckResults() : usesIO(false), hasImpureCalls(false) { }
LoopCheckResults(bool io, bool calls) : usesIO(io), hasImpureCalls(calls) { }
};
class LoopChecker
{
std::vector<LoopGraph*> &loopGraph;
LoopCheckResults checkLoopForPurenessAndIO(const LoopGraph *loopNode, const std::map<std::string, FuncInfo*> &allFuncs) const;
LoopCheckResults updateLoopNode(LoopGraph *loop, const std::map<std::string, FuncInfo*> &allFuncs);
public:
explicit LoopChecker(std::vector<LoopGraph*> &graph) : loopGraph(graph) { }
void updateLoopGraph(const std::map<std::string, FuncInfo*> &allFuncs);
};

View File

@@ -0,0 +1,341 @@
#include "leak_detector.h"
#include "ReadWriteAnalyzer.h"
using namespace std;
void ReadWriteAnalyzer::init(SgFile* forFile)
{
auto save = current_file->filename();
modified_pars = ReadWriteAnalyzer::load_modified_pars(funcInfo);
for (int j = 0; j < forFile->numberOfFunctions(); ++j)
{
SgStatement* func_hdr = forFile->functions(j);
SgStatement* last = func_hdr->lastNodeOfStmt();
for (SgStatement* runner = func_hdr->lexNext(); runner != last; runner = runner->lexNext())
{
// TODO: is it ok to skip all of them?
if (!isSgExecutableStatement(runner) || isDVM_stat(runner) || isSPF_stat(runner))
continue;
if (runner->variant() == CONTAINS_STMT)
break;
VarUsages usages = findUsagesInStatement(runner);
auto it = usages_by_statement.find(runner);
if (it != usages_by_statement.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
usages_by_statement[runner] = usages;
}
}
initialized.insert(forFile->filename());
if (SgFile::switchToFile(save) == -1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
VarUsages ReadWriteAnalyzer::findUsagesInStatement(SgStatement* st) const
{
// *special* statements, TODO: what i've missed?
if (st->variant() == ASSIGN_STAT)
return findUsagesInAssignment(st);
if (st->variant() == PROC_STAT)
return findUsagesInFuncCall(st->expr(0), st->symbol()->identifier());
else if (!isDVM_stat(st) && !isSPF_stat(st))
{
VarUsages st_usages;
for (int i = 0; i < 3; ++i)
st_usages.extend(findUsagesInExpr(st->expr(i)));
return st_usages;
}
return VarUsages();
}
VarUsages ReadWriteAnalyzer::findUsagesInAssignment(SgStatement* st) const
{
// load read & writes from the right part
VarUsages usages = findUsagesInExpr(st->expr(1));
// load usages from array indexes
VarUsages usages_in_arr_indexing = findUsagesInExpr(st->expr(1)->lhs());
usages.extend(usages_in_arr_indexing);
usages_in_arr_indexing = findUsagesInExpr(st->expr(1)->rhs());
usages.extend(usages_in_arr_indexing);
usages_in_arr_indexing = findUsagesInExpr(st->expr(0)->lhs());
usages.extend(usages_in_arr_indexing);
usages_in_arr_indexing = findUsagesInExpr(st->expr(0)->rhs());
usages.extend(usages_in_arr_indexing);
// finally add explicitly modified var
auto ex = st->expr(0);
auto s = st->expr(0)->symbol();
if (s && (ex->variant() == VAR_REF || isArrayRef(ex)))
usages.insert_write(ex);
return usages;
}
VarUsages ReadWriteAnalyzer::findUsagesInExpr(SgExpression* exp) const
{
VarUsages usages;
queue<SgExpression*> buf;
buf.push(exp);
while (!buf.empty())
{
SgExpression* cur = buf.front();
buf.pop();
if (!cur)
continue;
const int e_type = cur->variant();
if (e_type == VAR_REF || isArrayRef(cur))
usages.insert_read(cur);
else if (e_type == FUNC_CALL)
usages.extend(findUsagesInFuncCall(cur->lhs(), cur->symbol()->identifier()));
buf.push(cur->lhs());
buf.push(cur->rhs());
}
return usages;
}
void ReadWriteAnalyzer::findReadUsagesInExpression(SgExpression* ex, VarUsages& usages) const
{
if (ex)
{
if (ex->variant() == VAR_REF || ex->variant() == ARRAY_REF)
usages.insert_read(ex);
findReadUsagesInExpression(ex->lhs(), usages);
findReadUsagesInExpression(ex->rhs(), usages);
}
}
//TODO: need to improve to MPI_* functions
VarUsages ReadWriteAnalyzer::findUsagesInFuncCall(SgExpression* params_tree, const string& func_key) const
{
VarUsages usages;
vector<int> inOutTypes;
bool isIntrinsic = isIntrinsicFunctionName(func_key.c_str());
if (!isIntrinsic)
{
auto it = modified_pars.find(func_key);
if (it != modified_pars.end())
inOutTypes = it->second;
}
else if (isMpiFunction(func_key.c_str()))
{
if (func_key == "mpi_abort")
inOutTypes = { IN_BIT, IN_BIT, OUT_BIT };
if (func_key == "mpi_send")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
if (func_key == "mpi_isend")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_recv")
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_irecv")
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_alltoall")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_alltoallv")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_allgather")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_allgatherv")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_allreduce")
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_reduce")
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_reduce_scatter")
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_scatter")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_scatterv")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_gather")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_gatherv")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_sendrecv")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_sendrecv_replace")
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_scan")
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
else if (func_key == "mpi_bcast")
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
else if (func_key == "mpi_bsend")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT };
else if (func_key == "mpi_bsend_init")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
else if (func_key == "mpi_ibsend")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
else if (func_key == "mpi_irsend")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
else if (func_key == "mpi_issend")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
else if (func_key == "mpi_recv_init")
inOutTypes = { OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
else if (func_key == "mpi_rsend")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT };
else if (func_key == "mpi_rsend_init")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
else if (func_key == "mpi_send_init")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
else if (func_key == "mpi_ssend")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT };
else if (func_key == "mpi_ssend_init")
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
}
int param_no = 0;
while (params_tree)
{
SgExpression* param = params_tree->lhs();
if (param->variant() == VAR_REF || isArrayRef(param))
{
if (inOutTypes.size())
{
if (param_no >= inOutTypes.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (FuncParam::isArgIn((int64_t)inOutTypes[param_no]))
usages.insert_read(param);
if (FuncParam::isArgOut((int64_t)inOutTypes[param_no]))
usages.insert_write(param);
}
else
{
usages.insert_read(param);
if (!isIntrinsic)
usages.insert_write(param);
}
findReadUsagesInExpression(param->lhs(), usages);
findReadUsagesInExpression(param->rhs(), usages);
}
param_no++;
params_tree = params_tree->rhs();
}
return usages;
}
VarUsages ReadWriteAnalyzer::get_usages(SgStatement* st)
{
if (initialized.find(st->fileName()) == initialized.end())
init(st->getFile());
VarUsages usages;
// if statement is compound
if (compound_statements.find(st->variant()) != compound_statements.end())
usages = gatherUsagesForCompound(st);
else
{
auto it = usages_by_statement.find(st);
if (it == usages_by_statement.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
usages = it->second;
}
return usages;
}
VarUsages ReadWriteAnalyzer::get_usages(vector<SgStatement*> &statements)
{
auto usages = VarUsages();
for (auto& st : statements)
{
auto st_usages = get_usages(st);
usages.extend(st_usages);
}
return usages;
}
VarUsages ReadWriteAnalyzer::gatherUsagesForCompound(SgStatement* compoundStatement) const
{
VarUsages all_usages;
SgStatement* last = compoundStatement->lastNodeOfStmt();
SgStatement* runner = compoundStatement;
while (runner != last)
{
if (runner->variant() == CONTAINS_STMT)
break;
if (!isSgExecutableStatement(runner) || isDVM_stat(runner) || isSPF_stat(runner))
{
runner = runner->lexNext();
continue;
}
all_usages.extend(findUsagesInStatement(runner));
runner = runner->lexNext();
}
return all_usages;
}
void ReadWriteAnalyzer::print() const
{
auto save = current_file->filename();
for (int i = 0; i < CurrentProject->numberOfFiles(); i++)
{
printf("file: %s\n", CurrentProject->file(i).filename());
for (int j = 0; j < CurrentProject->file(i).numberOfFunctions(); j++)
{
printf("function: %s\n", CurrentProject->file(i).functions(j)->symbol()->identifier());
SgStatement* runner = CurrentProject->file(i).functions(j);
auto last = runner->lastNodeOfStmt();
while (runner != last)
{
if (runner->variant() == CONTAINS_STMT)
break;
auto it = usages_by_statement.find(runner);
if (it != usages_by_statement.end())
{
runner->unparsestdout();
it->second.print();
}
runner = runner->lexNext();
}
}
}
if (SgFile::switchToFile(save) == -1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
map<string, vector<int>> ReadWriteAnalyzer::load_modified_pars(const map<string, vector<FuncInfo*>> &files)
{
map<string, vector<int>> res;
for (auto& funcs : files)
{
string file_name = funcs.first;
for (auto& func : funcs.second)
{
string func_key = func->funcName;
res[func_key] = func->funcParams.inout_types;
}
}
return res;
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include "dvm.h"
#include "../Utils/SgUtils.h"
#include "VarUsages.h"
#include <set>
#include <tuple>
#include <queue>
#include <vector>
#include <exception>
#include <map>
class ReadWriteAnalyzer
{
std::map<std::string, std::vector<FuncInfo*>> &funcInfo; // TODO: could be not initilized; should be rebuilt on invalidate()
std::map<std::string, std::vector<int>> modified_pars; // func -> used for [in, inout, out] params,
std::map<SgStatement*, VarUsages> usages_by_statement; // maps statements to variables used in them
std::set<std::string> initialized; // files was inited
void init(SgFile*);
VarUsages findUsagesInStatement(SgStatement* st) const;
VarUsages findUsagesInAssignment(SgStatement* st) const;
void findReadUsagesInExpression(SgExpression* ex, VarUsages& toExtend) const;
const std::set<int> compound_statements = { FOR_NODE, LOOP_NODE, FUNC_HEDR, PROC_HEDR };
VarUsages gatherUsagesForCompound(SgStatement* st) const;
public:
explicit ReadWriteAnalyzer(std::map<std::string, std::vector<FuncInfo*>> &funcInfo) : funcInfo(funcInfo)
{ }
void invalidate(const std::string& fileName) { initialized.erase(fileName); }
VarUsages get_usages(SgStatement*);
VarUsages get_usages(std::vector<SgStatement*>&);
VarUsages findUsagesInExpr(SgExpression* exp) const;
VarUsages findUsagesInFuncCall(SgExpression*, const std::string&) const;
void print() const;
static std::map<std::string, std::vector<int>> load_modified_pars(const std::map<std::string, std::vector<FuncInfo*>>&);
};

View File

@@ -0,0 +1,195 @@
#include "leak_detector.h"
#include "RegionsMerger.h"
using namespace std;
bool RegionsMerger::compareByStart(const DvmhRegion *a, const DvmhRegion *b)
{
if (a->getLoops().size() < 1 || b->getLoops().size() < 1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
int lineLeft = a->getLoops()[0]->lineNum;
if (lineLeft < 0)
lineLeft = a->getLoops()[0]->altLineNum;
int lineRight = b->getLoops()[0]->lineNum;
if (lineRight < 0)
lineRight = b->getLoops()[0]->altLineNum;
return lineLeft < lineRight;
}
bool RegionsMerger::canBeMoved(SgStatement* st, const DvmhRegion *region) const
{
// For now: st [a, d = b + c] can be moved IF [b, c] are not modified in region AND [a, d] not used for read in region
// get usages for statement
VarUsages st_usages = rw_analyzer.get_usages(st);
// get usages for region
auto loop_statements = vector<SgStatement*>();
for (auto& loop : region->getLoops())
loop_statements.push_back(loop->loop);
auto region_usages = rw_analyzer.get_usages(loop_statements);
// analyze if statement can be placed before region
if (sets_intersect(st_usages.get_reads(), region_usages.get_writes())) // check that [b, c] not modified in region
return false;
if (sets_intersect(st_usages.get_writes(), region_usages.get_reads())) // check that [a, d] not read in region
return false;
return true; // everything's ok
}
vector<SgStatement*> RegionsMerger::getStatementsToMove(const DvmhRegion *first, const DvmhRegion *second, bool &can) const
{
// can not, abort operation
if (first->getFileName() != second->getFileName() || first->getFunName() != second->getFunName())
{
can = false;
return vector<SgStatement*>();
}
vector<SgStatement*> toMove;
SgStatement* mediumSt = first->getLastSt()->lexNext();
// skip DVM PARALLEL and hidden stats
while (mediumSt->variant() == DVM_PARALLEL_ON_DIR || mediumSt->variant() < 0)
mediumSt = mediumSt->lexNext();
//no statements between regions, so can
if (mediumSt == second->getFirstSt() && mediumSt->variant() == FOR_NODE)
{
can = true;
return vector<SgStatement*>();
} //TODO
else
{
can = false;
return vector<SgStatement*>();
}
//TODO: need to check and correct
while (mediumSt->id() != second->getFirstSt()->id())
{
if (mediumSt->variant() == DVM_PARALLEL_ON_DIR)
{
mediumSt = mediumSt->lexNext();
continue;
}
if (canBeMoved(mediumSt, first))
toMove.push_back(mediumSt);
else // can not, abort operation
{
can = false;
return vector<SgStatement*>();
}
mediumSt = mediumSt->lexNext();
}
return toMove;
}
// Places statements before region
void RegionsMerger::moveStatements(const vector<SgStatement*>& sts, const DvmhRegion* region)
{
SgStatement* prev = region->getFirstSt()->lexPrev();
while (isDVM_stat(prev))
prev = prev->lexPrev();
for (auto& st : sts)
{
SgStatement *toInsert = st->copyPtr();
prev->insertStmtAfter(*toInsert, *prev->controlParent());
prev = toInsert;
st->deleteStmt();
}
rw_analyzer.invalidate(region->getFileName());
}
vector<DvmhRegion*> RegionsMerger::mergeRegions()
{
if (regions.size() < 2)
return regions;
map<string, map<int, DvmhRegion*>> byFunc;
for (auto& elem : regions)
{
const int line = elem->getLineForSort();
const string fName = elem->getFunName();
auto& itF = byFunc[fName];
if (itF.find(line) != itF.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
itF[line] = elem;
}
vector<DvmhRegion*> newRegions;
for (auto& regsForFunc : byFunc)
{
map<int, DvmhRegion*>& regionsByFunc = regsForFunc.second;
if (regionsByFunc.size() == 0)
continue;
DvmhRegion* newRegion = new DvmhRegion();
DvmhRegion* regionPrev = regionsByFunc.begin()->second;
bool isFirst = true;
for (auto& loop : regionPrev->getLoops())
newRegion->addLoop(loop);
for (auto& region : regionsByFunc)
{
if (newRegion->getFunName() == "" && region.second->getLoops().size() > 0)
{
SgStatement* func_st = getFuncStat(region.second->getLoops()[0]->loop);
string fun_name = func_st->symbol()->identifier();
newRegion->setFunName(fun_name);
}
if (isFirst) // skip first region
{
isFirst = false;
continue;
}
bool can = true;
auto toMove = getStatementsToMove(regionPrev, region.second, can);
if (can)
{
//TODO
if (toMove.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
// moveStatements(toMove, regionPrev);
}
else
{
__spf_print(1, " region before loop on line %d (alt %d) cannot be merged\n",
region.second->getLoops()[0]->lineNum, region.second->getLoops()[0]->altLineNum);
toMove = getStatementsToMove(regionPrev, region.second, can);
newRegions.push_back(newRegion);
newRegion = new DvmhRegion();
}
newRegion->append(*region.second);
regionPrev = region.second;
}
newRegions.push_back(newRegion);
}
for (auto& old : regions)
delete old;
regions.clear();
return newRegions;
}
bool RegionsMerger::sets_intersect(const set<SgSymbol*>& set1, const set<SgSymbol*>& set2) const
{
for (auto& symb : set1)
if (set2.find(symb) != set2.end())
return true;
return false;
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include "DvmhRegions/DvmhRegionInserter.h"
class RegionsMerger
{
std::vector<DvmhRegion*> &regions;
ReadWriteAnalyzer &rw_analyzer;
bool canBeMoved(SgStatement* st, const DvmhRegion *region) const;
std::vector<SgStatement*> getStatementsToMove(const DvmhRegion *first, const DvmhRegion *second, bool&) const;
void moveStatements(const std::vector<SgStatement*>& sts, const DvmhRegion* region);
bool sets_intersect(const std::set<SgSymbol*>&, const std::set<SgSymbol*>&) const;
static bool compareByStart(const DvmhRegion* a, const DvmhRegion* b);
public:
explicit RegionsMerger(std::vector<DvmhRegion*>& old_regions, ReadWriteAnalyzer& rw) : regions(old_regions), rw_analyzer(rw) { }
std::vector<DvmhRegion*> mergeRegions();
};

View File

@@ -0,0 +1,36 @@
#include "leak_detector.h"
#include "TypedSymbol.h"
using namespace std;
TypedSymbol::TypedSymbol(SgExpression* orig_exp)
{
if (orig_exp->variant() == VAR_REF || orig_exp->variant() == ARRAY_REF)
orig = OriginalSymbol(orig_exp->symbol());
type = VAR_TYPE::VAR_UNDEFINED;
if (orig_exp->variant() == VAR_REF)
type = VAR_TYPE::VAR_SCALAR;
if (orig_exp->variant() == ARRAY_REF)
{
type = VAR_TYPE::VAR_ARR;
DIST::Array* arr = getArrayFromDeclarated(declaratedInStmt(orig), orig->identifier());
if (arr == NULL) //for strings charecter(*)
type = VAR_TYPE::VAR_SCALAR;
else if (!arr->IsNotDistribute())
type = VAR_TYPE::VAR_DISTR_ARR;
}
}
bool operator== (const TypedSymbol& lhs, const TypedSymbol& rhs)
{
return string(OriginalSymbol(lhs.orig)->identifier()) == string(OriginalSymbol(rhs.orig)->identifier()) &&
OriginalSymbol(lhs.orig)->scope()->id() == OriginalSymbol(rhs.orig)->scope()->id();
}
bool operator< (const TypedSymbol& lhs, const TypedSymbol& rhs)
{
return OriginalSymbol(lhs.orig)->id() < OriginalSymbol(rhs.orig)->id();
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include "dvm.h"
#include "../Utils/SgUtils.h"
#include <string>
enum class VAR_TYPE { VAR_ARR, VAR_DISTR_ARR, VAR_SCALAR, VAR_ANY, VAR_UNDEFINED };
class TypedSymbol
{
public:
SgSymbol* orig;
VAR_TYPE type;
TypedSymbol(SgExpression*);
friend bool operator== (const TypedSymbol& lhs, const TypedSymbol& rhs);
friend bool operator< (const TypedSymbol& lhs, const TypedSymbol& rhs);
};

View File

@@ -0,0 +1,97 @@
#include "leak_detector.h"
#include "VarUsages.h"
using namespace std;
void VarUsages::extend(const VarUsages& to_insert)
{
undefined |= to_insert.undefined;
reads.insert(to_insert.reads.begin(), to_insert.reads.end());
writes.insert(to_insert.writes.begin(), to_insert.writes.end());
}
set<SgSymbol*> VarUsages::get_reads(const set<VAR_TYPE> var_type) const
{
if (undefined)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return filter(reads, var_type);
}
set<SgSymbol*> VarUsages::get_writes(const set<VAR_TYPE> var_type) const
{
if (undefined)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return filter(writes, var_type);
}
set<SgSymbol*> VarUsages::get_all(const set<VAR_TYPE> var_type) const
{
set<TypedSymbol> all_usages;
all_usages.insert(reads.begin(), reads.end());
all_usages.insert(writes.begin(), writes.end());
return filter(all_usages, var_type);
}
set<SgSymbol*> VarUsages::get_reads() const { return get_reads({ VAR_TYPE::VAR_ANY }); }
set<SgSymbol*> VarUsages::get_writes() const { return get_writes({ VAR_TYPE::VAR_ANY }); }
set<SgSymbol*> VarUsages::get_all() const { return get_all({ VAR_TYPE::VAR_ANY }); }
set<SgSymbol*> VarUsages::filter(const set<TypedSymbol> &symbols, const set<VAR_TYPE> var_type)
{
set<SgSymbol*> filtered;
if (var_type.find(VAR_TYPE::VAR_ANY) != var_type.end())
for (auto& s : symbols)
filtered.insert(s.orig);
else
for (auto& s : symbols)
if (var_type.find(s.type) != var_type.end())
filtered.insert(s.orig);
return filtered;
}
void VarUsages::insert_undefined(const TypedSymbol& s)
{
undefined = true;
reads.insert(s);
writes.insert(s);
}
void VarUsages::insert_read(const TypedSymbol& s) { reads.insert(s); }
void VarUsages::insert_write(const TypedSymbol& s) { writes.insert(s); }
void VarUsages::print() const
{
printf("reads: ");
if (undefined)
printf("not_defined");
else
{
for (auto& s : reads)
printf("%s ", s.orig->identifier());
}
printf("\n");
printf("writes: ");
if (undefined)
printf("not_defined");
else
{
for (auto& s : writes)
printf("%s ", s.orig->identifier());
}
printf("\n");
printf("all: ");
for (auto& s : get_all({ VAR_TYPE::VAR_ANY }))
printf("%s ", s->identifier());
printf("\n");
printf("***\n");
}
bool VarUsages::is_undefined() const { return undefined; }

View File

@@ -0,0 +1,33 @@
#pragma once
#include "dvm.h"
#include "TypedSymbol.h"
#include <set>
class VarUsages
{
std::set<TypedSymbol> reads;
std::set<TypedSymbol> writes;
bool undefined;
public:
VarUsages() : undefined(false) { }
void extend(const VarUsages&);
void insert_undefined(const TypedSymbol&);
void insert_read(const TypedSymbol&);
void insert_write(const TypedSymbol&);
bool is_undefined() const;
std::set<SgSymbol*> get_reads(const std::set<VAR_TYPE>) const;
std::set<SgSymbol*> get_writes(const std::set<VAR_TYPE>) const;
std::set<SgSymbol*> get_all(const std::set<VAR_TYPE>) const;
std::set<SgSymbol*> get_reads() const;
std::set<SgSymbol*> get_writes() const;
std::set<SgSymbol*> get_all() const;
static std::set<SgSymbol*> filter(const std::set<TypedSymbol>&, const std::set<VAR_TYPE>);
void print() const;
};

View File

@@ -0,0 +1,357 @@
#include "dvm.h"
#include <stdio.h>
#include <iostream>
#include "./createParallelRegions.h"
#include "../CreateInterTree/CreateInterTree.h"
#include "../GraphCall/graph_calls.h"
#include "./gcov_info.h"
#include "./gCov_parser_func.h"
#include "../Utils/leak_detector.h"
#include <map>
#include <vector>
#include <string>
#include <stack>
using std::vector;
using std::map;
using std::string;
using std::stack;
using std::pair;
using std::to_string;
static void markNestedIntervals(SpfInterval *interval)
{
for (auto &item : interval->nested)
{
item->isNested = true;
if (!item->begin->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (item->begin->symbol()->identifier() != NULL)
markNestedIntervals(item);
}
}
static int countOfIntervals(const SpfInterval *interval, const SpfInterval *mainInterval)
{
int count = 0;
for (auto &item : mainInterval->nested)
{
if (item == interval)
count++;
else
count += countOfIntervals(interval, item);
}
return count;
}
static void performFuncTime(const map<string, vector<FuncInfo*>> &funcInfo, map<string, int> &countFunc)
{
int count = 0;
for (auto &str : funcInfo)
{
count = 0;
for (auto *info : str.second)
{
count += (info->callsTo).size();
if (countFunc.find(info->funcName) != countFunc.end())
countFunc[info->funcName] += count;
else
countFunc.insert(make_pair(info->funcName, count));
}
}
}
double performTime(SgProject* project, SgStatement *src, const map<string, map<int, Gcov_info>> &gCovInfo, map<string, int> &calls, int recLevel)
{
SgStatement* stmt = src;
if (!src->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (!isSgExecutableStatement(stmt))
return 0.0;
auto gCovForFile = gCovInfo.find(string(stmt->fileName()));
if (gCovForFile == gCovInfo.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto gCovForStmt = gCovForFile->second.find(stmt->lineNumber());
if (gCovForStmt == gCovForFile->second.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const Gcov_info& info = gCovForStmt->second;
double count = 0.0;
switch (stmt->variant())
{
case PROC_STAT:
{
if (recLevel <= 5)
{
SgCallStmt *call = (SgCallStmt*)src;
if (info.getCountCalls() == 0)
break;
SgStatement *body = NULL;
string funcName(call->name()->identifier());
auto num = calls.find(funcName);
// its not a user function
if (num == calls.end())
break;
for (int j = 0; j < project->numberOfFiles(); ++j)
{
SgFile& file = project->file(j);
if (SgFile::switchToFile(file.filename()) == -1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int i = 0; i < file.numberOfFunctions(); ++i)
{
if (!strcmp(file.functions(i)->symbol()->identifier(), funcName.c_str()))
{
body = file.functions(i);
break;
}
}
}
if (body == NULL)
break;
while (body && body->variant() != RETURN_STAT)
{
count += performTime(project, body, gCovInfo, calls, recLevel + 1);
if (!body->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
body = body->lexNext();
}
count /= num->second;
}
break;
}
case IF_NODE:
case LOGIF_NODE:
case ELSEIF_NODE:
{
SgIfStmt* ifSt = (SgIfStmt*)src;
SgStatement* tmp = ifSt->trueBody();
int t = 0;
while (tmp->variant() != CONTROL_END)
{
t += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
tmp = tmp->lexNext();
}
count += (info.getBranches()[0].getPercent()) * 0.01 * t;
t = 0;
tmp = ifSt->falseBody();
while (tmp && tmp->variant() != CONTROL_END)
{
t += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
tmp = tmp->lexNext();
}
count += (info.getBranches()[1].getPercent()) * 0.01 * t;
break;
}
case WHILE_NODE:
{
SgWhileStmt* whileSt = (SgWhileStmt*)src;
SgStatement* tmp = whileSt->body();
while (tmp->variant() != CONTROL_END)
{
count += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
if (!tmp->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
tmp = tmp->lexNext();
}
break;
}
case FOR_NODE:
{
SgForStmt* forSt = (SgForStmt*)src;
SgStatement* tmp = forSt->body();
while (tmp->variant() != CONTROL_END)
{
count += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
if (!tmp->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
tmp = tmp->lexNext();
}
break;
}
case ADD_OP:
case MULT_OP:
case DIV_OP:
case SUB_OP:
case ASSGN_OP:
case ASSIGN_STAT:
// let frequency be about 2 GHerz
count += 0.0000000005 * info.getExecutedCount();
break;
case WRITE_STAT:
case READ_STAT:
// read/write operations are slower
count += 0.0000000015 * info.getExecutedCount();
break;
default:
break;
}
return count;
}
typedef pair<vector<SpfInterval*>, int> PositionInVector;
typedef stack<PositionInVector> IntervalStack;
double performIntervalTime(SgProject* project, const SpfInterval *interval, const map<string, map<int, Gcov_info>> &gCovInfo, map<string, int> &calls)
{
double time = 0.0;
for (SgStatement *stat = interval->begin; stat != interval->ends[interval->ends.size() - 1]; stat = stat->lexNext())
{
time += performTime(project, stat, gCovInfo, calls, 0);
if (!stat->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
return time;
}
void createParallelRegions(SgProject* project, SpfInterval *mainInterval, const map<string, map<int, Gcov_info>> &gCovInfo, const map<string, vector<FuncInfo*>> &funcInfo)
{
double percent = 0.8;
vector<SpfRegion> regions;
map<string, int> calls;
performFuncTime(funcInfo, calls);
if (mainInterval == NULL)
{
__spf_print(1, "internal error in analysis, directives will not be generated for this file!\n");
return;
}
double sumTime = performIntervalTime(project, mainInterval, gCovInfo, calls);
double alreadyHavePercent = 0.0;
int id = 1;
int i = 0;
IntervalStack stack;
vector<SpfInterval*> iterated;
vector<SpfInterval*> nested;
iterated.push_back(mainInterval);
while (alreadyHavePercent <= percent)
{
if (i >= iterated.size())
{
if (!stack.empty())
{
iterated = stack.top().first;
i = stack.top().second;
stack.pop();
}
else
break;
}
SpfInterval* interval = iterated[i];
if (!interval || interval->isRegion || interval->isNested)
{
i++;
continue;
}
double time = performIntervalTime(project, interval, gCovInfo, calls);
int count = countOfIntervals(interval, mainInterval);
if (count != 0) time *= count;
double percentOfInterval = time / sumTime;
if (percentOfInterval + alreadyHavePercent <= percent)
{
__spf_print(1, "Add interval with %f percent, we have %f percent\n", percentOfInterval, percentOfInterval + alreadyHavePercent);
SpfRegion region(id, time, interval->begin, interval->ends[0]);
region.time = time;
region.id = id;
iterated[i]->isRegion = true;
markNestedIntervals(interval);
id++;
i++;
regions.push_back(region);
alreadyHavePercent += percentOfInterval;
}
else
{
__spf_print(1, "divide interval with %f percent\n", percentOfInterval);
if (i < iterated.size() - 1)
stack.push(make_pair(vector<SpfInterval*>(iterated.begin(), iterated.end()), i + 1));
iterated.clear();
iterated = vector<SpfInterval*>(interval->nested.begin(), interval->nested.end());
i = 0;
}
}
i = 0;
while (i < regions.size())
{
if (i > 0 && !regions[i-1].end->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (i > 0 && regions[i - 1].end->lexNext() == regions[i].start)
{
regions[i - 1].end = regions[i].end;
regions.erase(regions.begin() + i);
continue;
}
i++;
}
__spf_print(1, "Coverage of region is %f percent, count of regions is %d\n", alreadyHavePercent, regions.size());
for (auto &item : regions)
{
if (!item.start->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
SgStatement *startRegion = new SgStatement(SPF_PARALLEL_REG_DIR);
SgStatement *endRegion = new SgStatement(SPF_END_PARALLEL_REG_DIR);
startRegion->setSymbol(*(new SgSymbol(VARIABLE_NAME, to_string(item.id).c_str())));
SgStatement *st = item.start;
while (!isSgExecutableStatement(st))
st = st->lexNext();
startRegion->setFileId(st->getFileId());
startRegion->setProject(st->getProject());
startRegion->setlineNumber(st->lineNumber());
startRegion->setFileName(st->fileName());
st->insertStmtBefore(*startRegion, *st->controlParent());
SgStatement *next = item.end->lexNext();
startRegion->setFileId(next->getFileId());
startRegion->setProject(next->getProject());
startRegion->setlineNumber(next->lineNumber());
startRegion->setFileName(next->fileName());
next->insertStmtBefore(*endRegion, *next->controlParent());
}
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include "../Utils/utils.h"
#include "./gcov_info.h"
#include "../CreateInterTree/CreateInterTree.h"
#include "../GraphCall/graph_calls.h"
#include <map>
#include <vector>
struct SpfRegion
{
int id;
double time;
SgStatement *start;
SgStatement *end;
SpfRegion(int id_, int time_, SgStatement *start_, SgStatement *end_) :
id(id_), time(time_), start(start_), end(end_) {}
SpfRegion& operator+=(const SpfRegion &rg)
{
if (this != &rg)
{
end = rg.end;
time += rg.time;
}
return *this;
}
};
void createParallelRegions(SgProject *project, SpfInterval *mainInterval, const std::map<std::string, std::map<int, Gcov_info>> &gCovInfo, const std::map<std::string, std::vector<FuncInfo*>> &funcInfo);

View File

@@ -0,0 +1,473 @@
#include "../Utils/leak_detector.h"
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <string>
#include <map>
#include "dvm.h"
#include "gCov_parser_func.h"
#include "../Utils/SgUtils.h"
using namespace std;
enum key_word
{
UNKNOWN,
BRANCH,
CALL,
};
static const char *key_words[] =
{
"",
"branch",
"call",
"taken",
"returned",
NULL
};
static const char *symbols_neverExecuted[] =
{
"",
"#####",
"%%%%%",
"$$$$$",
"=====",
NULL
};
static void isKeyWord(const string &lex, key_word &lineType)
{
int i = 1;
bool find = false;
while ((!find) && key_words[i]) {
if (lex.compare(key_words[i]) == 0)
find = true;
else
i++;
}
switch (i) {
case 1:
lineType = BRANCH;
break;
case 2:
lineType = CALL;
break;
default:
if (lineType != UNKNOWN)
{
__spf_print(1, "Error: Wrong work of analysis keywords\n");
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}
}
static bool isNeverExecuted(const string &lex)
{
int i = 1;
bool find = false;
while ((!find) && symbols_neverExecuted[i])
{
if (lex.compare(symbols_neverExecuted[i]) == 0)
find = true;
else
i++;
}
return find;
}
static void getInfo(map<int, Gcov_info> &info, const string &str)
{
Gcov_info infoLine;
Perform infoPerform;
string num, lex;
key_word lineType = UNKNOWN;
bool executedCountGot = false;
int i = 0;
int len = str.length();
int minus = 0;
int ddot = 0;
while (i != len)
{
char c = str[i];
if ((c >= 48) && (c <= 57)) //symbols '0'-'9'
num.push_back(c);
else
{
switch (c)
{
case ' ':
if ((!lex.empty()) && (lineType == UNKNOWN))
isKeyWord(lex, lineType);
lex.clear();
if ((!num.empty()) && ((lineType == BRANCH) || (lineType == CALL)))
infoPerform.setNumber(stoi(num, nullptr));
num.clear();
break;
case ':':
ddot++;
if ((!lex.empty()) && (isNeverExecuted(lex)))
{
executedCountGot = true;
infoLine.setExecutedCount(0);
}
if (!num.empty())
{
if (!executedCountGot)
{
const int64_t value = stoll(num);
if (minus == 1 && ddot == 1 && value == 0)
infoLine.setExecutedCount(-1);
else
infoLine.setExecutedCount(value);
executedCountGot = true;
}
else
infoLine.setNumLine(stoi(num, nullptr));
}
num.clear();
break;
case '%':
if (!num.empty())
infoPerform.setPercent(stoi(num, nullptr));
num.clear();
break;
case '-':
minus++;
num.push_back('0');
break;
default:
//Try find 'branch' or 'call'
lex.push_back(c);
}
}
i++;
}
if (infoLine.getNumLine() != -1)
info.insert(make_pair(infoLine.getNumLine(), infoLine));
switch (lineType)
{
case BRANCH:
((*(info.rbegin())).second).setBranch(infoPerform);
break;
case CALL:
((*(info.rbegin())).second).setCall(infoPerform);
break;
case UNKNOWN:
break;
default:
__spf_print(1, "Error: get unreal type\n");
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
break;
}
}
static void printPerform(map<int, Perform> info, ostream &myfile)
{
map<int, Perform>::iterator cur;
for (cur = info.begin(); cur != info.end(); cur++)
myfile << (*cur).first << ")" << (*cur).second;
}
static void printInfo2file(map<int, Gcov_info> &info, ostream &myfile)
{
map<int, Gcov_info>::iterator cur;
for (cur = info.begin(); cur != info.end(); cur++)
{
Gcov_info cur_gcov = (*cur).second;
myfile << "_________________\n";
myfile << "" << (*cur).first << endl << cur_gcov;
if (cur_gcov.getCountCalls() != 0)
{
myfile << "-----Calls----\n";
printPerform(cur_gcov.getCalls(), myfile);
}
if (cur_gcov.getCountBranches() != 0)
{
myfile << "----Branches----\n";
printPerform(cur_gcov.getBranches(), myfile);
}
}
}
static inline string modify_name(const string &name)
{
return name + "_pgcov.txt";
}
/*
-добавить флаги при компиляции : gfortran -O2 -g -fprofile-arcs -ftest-coverage
- запустить программу
- отдать исходник профилировщику с флагом : LANG=en_US.utf8 gcov -b file.f
*/
static void fixGcovInfo(SgFile *fileSg, map<int, Gcov_info> &gCovInfo)
{
for (SgStatement *st = fileSg->firstStatement(); st; st = st->lexNext())
{
if (isSgExecutableStatement(st) && !isDVM_stat(st) && !isSPF_stat(st) &&
(st->variant() != DVM_INTERVAL_DIR && st->variant() != DVM_ENDINTERVAL_DIR))
{
auto next = st->lexNext();
const int currLine = st->lineNumber();
const int nextLine = next ? next->lineNumber() : -1;
if (next)
{
if (nextLine == currLine)
continue;
auto it = gCovInfo.find(currLine);
if (it != gCovInfo.end())
{
if (it->second.getExecutedCount() <= 0)
{
int nextL = currLine + 1;
while (nextL != nextLine)
{
auto itNext = gCovInfo.find(nextL);
if (itNext != gCovInfo.end())
{
if (itNext->second.getExecutedCount() >= 0)
{
it->second.clear();
it->second.setExecutedCount(itNext->second.getExecutedCount());
for (auto &call : itNext->second.getCalls())
it->second.setCall(call.second);
for (auto &branch : itNext->second.getBranches())
it->second.setBranch(branch.second);
// copy to between
for (int z = currLine + 1; z != nextL; ++z)
{
auto itZ = gCovInfo.find(z);
if (itZ != gCovInfo.end())
{
itZ->second.clear();
itZ->second.setExecutedCount(itNext->second.getExecutedCount());
for (auto &call : itNext->second.getCalls())
itZ->second.setCall(call.second);
for (auto &branch : itNext->second.getBranches())
itZ->second.setBranch(branch.second);
}
}
break;
}
}
nextL++;
}
}
}
}
}
}
for (SgStatement *st = fileSg->firstStatement(); st; st = st->lexNext())
{
if (isSgExecutableStatement(st) && !isDVM_stat(st) && !isSPF_stat(st) &&
(st->variant() != DVM_INTERVAL_DIR && st->variant() != DVM_ENDINTERVAL_DIR))
{
if (st->variant() == CONTROL_END)
{
auto cp = st->controlParent();
auto it = gCovInfo.find(cp->lineNumber());
if (it != gCovInfo.end() && cp->variant() != PROG_HEDR &&
cp->variant() != PROC_HEDR && cp->variant() != FUNC_HEDR &&
isSgExecutableStatement(cp))
{
auto it = gCovInfo.find(st->lineNumber());
auto itCp = gCovInfo.find(cp->lineNumber());
if (it != gCovInfo.end())
{
it->second.clear();
it->second.setExecutedCount(itCp->second.getExecutedCount());
for (auto &call : itCp->second.getCalls())
it->second.setCall(call.second);
for (auto &branch : itCp->second.getBranches())
it->second.setBranch(branch.second);
}
}
continue;
}
}
}
}
static map<string, map<int, Gcov_info>*> allGCovInfo;
void parse_gcovfile(SgFile *fileSg, const string &basefileNameIn, map<int, Gcov_info> &gCovInfo, bool keep)
{
if (basefileNameIn == "")
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
else
{
const string basefileName = basefileNameIn + ".gcov";
ifstream file;
file.open(basefileName, ios::in);
if (file.is_open())
{
string str;
while (!file.eof())
{
getline(file, str);
getInfo(gCovInfo, str);
}
file.close();
fixGcovInfo(fileSg, gCovInfo);
if (keep)
{
// FOR DEBUG ONLY
string name_f = modify_name(basefileName);
ofstream myfile(name_f);
if (myfile.is_open())
printInfo2file(gCovInfo, myfile);
else
__spf_print(1, " Error: unable to create file %s\n", name_f.c_str());
}
}
else
__spf_print(1, " Error: unable to open file %s\n", basefileName.c_str());
}
allGCovInfo[fileSg->filename()] = &gCovInfo;
}
bool __gcov_doesThisLineExecuted(const string &file, const int line)
{
bool ret = true;
auto itF = allGCovInfo.find(file);
if (itF != allGCovInfo.end())
{
auto itL = itF->second->find(line);
if (itL != itF->second->end())
ret = itL->second.getExecutedCount() != 0;
}
return ret;
}
pair<int, int64_t> __gcov_GetExecuted(const string &file, const int line)
{
pair<int, int64_t> ret = make_pair(0, 0);
auto itF = allGCovInfo.find(file);
if (itF != allGCovInfo.end())
{
auto itL = itF->second->find(line);
if (itL != itF->second->end())
ret.second = itL->second.getExecutedCount();
else
ret.first = -1;
}
else
ret.first = -1;
return ret;
}
void parseTimesDvmStatisticFile(const string &file, map<string, vector<SpfInterval*>> &intervals)
{
map<string, map<int, SpfInterval*>> mapOfIntervals;
for (auto &intByfile : intervals)
createMapOfinterval(mapOfIntervals[intByfile.first], intByfile.second);
FILE *stat = fopen(file.c_str(), "r");
if (stat)
{
char buf[8192];
int execDone = 1;
int line = -1;
string fileN = "";
SpfInterval *curr = NULL;
while (!feof(stat))
{
char *read = fgets(buf, 8192, stat);
if (read)
{
const string origLine(read);
auto itF = origLine.find("INTERVAL");
auto itTypeU = origLine.find("USER");
auto itExpr = origLine.find("EXPR=");
if (itF != string::npos && itTypeU != string::npos && itExpr != string::npos)
{
execDone = 0;
line = -1;
fileN = "";
int expr = 0;
curr = NULL;
auto itL = origLine.find("NLINE=");
if (itL != string::npos)
{
string lineS = "";
for (size_t z = itL + 6; origLine[z] != ' '; ++z)
lineS += origLine[z];
line = atoi(lineS.c_str());
}
auto itS = origLine.find("SOURCE=");
if (itS != string::npos)
{
string source = "";
for (size_t z = itS + 7; origLine[z] != ' '; ++z)
source += origLine[z];
fileN = source;
convertToLower(fileN);
}
string exprS = "";
for (size_t z = itExpr + 5; origLine[z] != '\n'; ++z)
exprS += origLine[z];
expr = atoi(exprS.c_str());
if (line != -1 && fileN != "")
{
auto itIntF = mapOfIntervals.find(fileN);
if (itIntF == mapOfIntervals.end())
{
//TODO: error
}
else
{
for (auto &inter : itIntF->second)
{
if (inter.second->tag == expr)
{
curr = inter.second;
string execCountS = "";
auto itExec = origLine.find("EXE_COUNT=");
string execS = "";
for (size_t z = itExec + 10; origLine[z] != ' '; ++z)
execS += origLine[z];
inter.second->exec_count = atoi(execS.c_str());
break;
}
}
}
}
}
auto itE = origLine.find("Execution time");
if (itE != string::npos && execDone == 0)
{
execDone = 1;
size_t idx = 16;
while (origLine[idx++] == ' ');
string execC = "";
for (size_t z = idx - 1; z < origLine.size(); ++z)
execC += origLine[z];
double execTime = atof(execC.c_str());
if (line != -1 && fileN != "" && curr)
curr->exec_time += execTime;
}
}
}
fclose(stat);
}
else
__spf_print(1, " Error: unable to open file %s\n", file.c_str());
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <string>
#include <map>
#include <vector>
#include "dvm.h"
#include "../Utils/errors.h"
#include "gcov_info.h"
#include "../CreateInterTree/CreateInterTree.h"
void parse_gcovfile(SgFile *file, const std::string &basefileName, std::map<int, Gcov_info> &gCovInfo, bool keep);
bool __gcov_doesThisLineExecuted(const std::string &file, const int line);
std::pair<int, int64_t> __gcov_GetExecuted(const std::string &file, const int line);
void parseTimesDvmStatisticFile(const std::string &file, std::map<std::string, std::vector<SpfInterval*>> &intervals);

View File

@@ -0,0 +1,48 @@
#include "../Utils/leak_detector.h"
#include <iostream>
#include <map>
#include <algorithm>
#include "../Utils/errors.h"
#include "gcov_info.h"
using std::map;
using std::make_pair;
using std::ostream;
using std::endl;
Gcov_info::Gcov_info() { numLine = -1; executedCount = -1; countCalls = 0; countBranches = 0; }
Gcov_info::Gcov_info(int a, int b) { numLine = a; executedCount = b; }
void Gcov_info::set(int a, int64_t b, int c, int d) { numLine = a; executedCount = b; countCalls = c; countBranches = d; }
int Gcov_info::getNumLine() const { return numLine; }
int64_t Gcov_info::getExecutedCount() const { return executedCount; }
void Gcov_info::setNumLine(int a) { numLine = a; }
void Gcov_info::setExecutedCount(int64_t a) { executedCount = a; }
void Gcov_info::setCall(Perform a) { countCalls++; calls.insert(make_pair(a.getNumber(), a)); }
void Gcov_info::setBranch(Perform a) { countBranches++; branches.insert(make_pair(a.getNumber(), a)); }
map<int, Perform> Gcov_info::getCalls() const { return calls; }
map<int, Perform> Gcov_info::getBranches() const { return branches; }
int Gcov_info::getCountCalls() const { return countCalls; }
int Gcov_info::getCountBranches() const { return countBranches; }
void Gcov_info::gcov_print() const { __spf_print(1, "%d - %lld\n", numLine, executedCount); }
ostream &operator<<(ostream &out, const Gcov_info &a) {
out << "numLine= " << a.numLine << "\nexecutedCount= " << a.executedCount <<
"\ncountCalls= " << a.countCalls << "\ncountBranches= " << a.countBranches << endl;
return out;
}
//-------------------------Perform-----------------------------------------
Perform::Perform() { number = -1; percent = -1; }
Perform::Perform(int a, int b) { number = a; percent = b; }
void Perform::set(int a, int b) { number = a; percent = b; }
int Perform::getNumber() { return number; }
int Perform::getPercent() { return percent; }
void Perform::setNumber(int a) { number = a; }
void Perform::setPercent(int a) { percent = a; }
void Perform::gcov_print() { __spf_print(1, "%d - %d\n", number, percent); }
ostream &operator<<(ostream &out, const Perform &a) { out << "number= " << a.number << ": percent= " << a.percent << endl; return out; }

View File

@@ -0,0 +1,53 @@
#pragma once
#include <stdio.h>
#include <string>
#include <map>
#include <stdint.h>
#include "../Utils/utils.h"
//make 'class' - need friend for Gcov_info
struct Perform
{
int number;
int percent;
Perform();
Perform(int a, int b);
void set(int a, int b);
int getNumber();
int getPercent();
void setNumber(int a);
void setPercent(int a);
void gcov_print();
friend std::ostream &operator<<(std::ostream &out, const Perform &a);
};
class Gcov_info
{
int numLine;
int64_t executedCount;
int countCalls;
std::map<int, Perform> calls;
int countBranches;
std::map<int, Perform> branches;
public:
Gcov_info();
Gcov_info(int a, int b);
void set(int a, int64_t b, int c, int d);
void clear() { calls.clear(); branches.clear(); countCalls = 0; countBranches = 0; }
int getNumLine() const;
int64_t getExecutedCount() const;
void setNumLine(int a);
void setExecutedCount(int64_t a);
int getCountCalls() const;
int getCountBranches() const;
std::map<int,Perform> getCalls() const;
std::map<int,Perform> getBranches() const;
void setCall(Perform a);
void setBranch(Perform a);
void gcov_print() const;
friend std::ostream &operator<<(std::ostream &out, const Gcov_info &a);
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,128 @@
#pragma once
#include <map>
#include <set>
#include <string>
#include "dvm.h"
#include "../Distribution/Distribution.h"
#include "../GraphLoop/graph_loops.h"
#include "../ParallelizationRegions/ParRegions.h"
#include "../GraphCall/graph_calls.h"
#include "../Utils/SgUtils.h"
#include "acc_analyzer.h"
struct VariableItem;
class VarsKeeper;
class DataFlowItem;
SgExpression* ReplaceParameter_(SgExpression* e);
SgExpression* ReplaceArrayBoundSizes(SgExpression *edim);
SgExpression* ReplaceConstant(SgExpression *e);
void getCoefsOfSubscript(std::pair<int, int> &retCoefs, SgExpression *exp, SgSymbol *doName);
void createLinksToCopy(SgExpression* exOrig, SgExpression* exCopy);
int CalculateInteger(SgExpression *expr, int &result);
SgExpression* CalculateInteger(SgExpression *expr);
void expressionAnalyzer(SgFile *file,
const std::map<std::string, std::vector<DefUseList>> &defUseByFunctions,
const std::map<std::string, CommonBlock*> &commonBlocks,
const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo,
const std::vector<ParallelRegion*> &regions);
bool calculate(SgExpression *&exp);
bool replaceConstantRec(SgExpression *&exp);
enum REPLACE_PTR_TYPE { SG_EXPRESSION, SG_STATEMENT };
void revertReplacements(const std::string &filename, bool back = false);
struct GraphItem {
GraphItem(): CGraph(NULL), file_id(-1), calls(CallData()), commons(CommonData()), dldl(DoLoopDataList()), privateDone(false) {}
int file_id;
ControlFlowGraph* CGraph;
CallData calls;
CommonData commons;
DoLoopDataList dldl;
bool privateDone;
~GraphItem() { if(CGraph) delete CGraph; }
};
class GraphsKeeper {
private:
std::map<SgStatement*, GraphItem*> graphs;
GraphsKeeper(): graphs(std::map<SgStatement*, GraphItem*>()) {}
public:
static GraphsKeeper* getGraphsKeeper();
static void deleteGraphsKeeper();
~GraphsKeeper()
{
for (auto &it : graphs)
if (it.second)
{
delete it.second;
it.second = NULL;
}
graphs.clear();
}
GraphItem* buildGraph(SgStatement* st);
GraphItem* getGraph(SgStatement *header);
CBasicBlock* findBlock(SgStatement* stmt);
};
struct FuncCallSE
{
std::string funcName;
std::set<std::string> calls;
FuncCallSE(std::string &n, std::set<std::string>& v) : funcName(n), calls(v) {}
};
class CommonVarsOverseer
{
private:
bool inited;
public:
std::map<std::string, std::set<SgSymbol*>> funcKillsVars;
CommonVarsOverseer() : inited(false), funcKillsVars(std::map<std::string, std::set<SgSymbol*>>()) {}
bool isInited() { return inited; }
void riseInited() { inited = true; }
void addKilledVar(SgSymbol* symbol, const std::string &funcName)
{
auto founded = funcKillsVars.find(funcName);
if (founded == funcKillsVars.end())
funcKillsVars.insert(founded, std::make_pair(funcName, std::set<SgSymbol*>()))->second.insert(symbol);
else
founded->second.insert(symbol);
}
std::set<SgSymbol*>* killedVars(const std::string &funcName)
{
auto founded = funcKillsVars.find(funcName);
if (founded == funcKillsVars.end())
return NULL;
return &(founded->second);
}
};
std::map<SgStatement*, std::pair<std::set<SgStatement*>, std::set<SgStatement*>>> buildRequireReachMapForLoop(SgStatement *since, SgStatement *till, std::set<std::string> &privates);
const std::map<SymbolKey, std::set<ExpressionValue*>> getReachingDefinitionsExt(SgStatement* stmt);
void FillCFGInsAndOutsDefs(ControlFlowGraph*, std::map<SymbolKey, std::set<ExpressionValue*>> *inDefs, CommonVarsOverseer *overseer_Ptr);
void CorrectInDefs(ControlFlowGraph*);
void ClearCFGInsAndOutsDefs(ControlFlowGraph*);
bool valueWithRecursion(const SymbolKey&, SgExpression*);
bool valueWithFunctionCall(SgExpression*);
bool valueWithArrayReference(SgExpression *exp, SgStatement* from);
bool argIsReplaceable(int i, AnalysedCallsList* callData);
bool argIsUsed(int i, AnalysedCallsList* callData);
bool symbolInExpression(const SymbolKey &symbol, SgExpression *exp);
void showDefs(std::map<SymbolKey, std::set<ExpressionValue>> *defs);
void showDefs(std::map<SymbolKey, SgExpression*> *defs);
void showDefsOfGraph(ControlFlowGraph *CGraph);
void debugStructure(ControlFlowGraph *CGraph, const std::string &filename);
bool findCFIsForStmt(SgStatement *st, std::vector <ControlFlowItem*> &cfis);
std::map<SymbolKey, std::set<ExpressionValue*>> createHeaderInDefs(SgStatement *header);
ControlFlowGraph* BuildUnfilteredReachingDefinitionsFor(SgStatement *header);
void runPrivateAnalysis(SgStatement *main);
SgStatement* findReplacedExpression(SgExpression* ex);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,315 @@
#pragma once
#include <string>
#include <set>
#include "../Utils/AstWrapper.h"
#include "../Utils/utils.h"
#include "../DirectiveProcessing/shadow.h"
#include "../GraphLoop/graph_loops.h"
static const char* paramNames[] =
{ "NONE_T", "ARRAY_T", "STRING_ARRAY_T", "STRING_T", "SCALAR_CHAR_T", "SCALAR_BOOL_T", "SCALAR_SHORT_T", "SCALAR_INT_T", "SCALAR_LONG_INT_T",
"SCALAR_FLOAT_T", "SCALAR_DOUBLE_T",
"SCALAR_CMPLX_FLOAT_T", "SCALAR_CMPLX_DOUBLE_T", "EXTERNAL_T", "UNKNOWN_T" };
typedef enum parF { NONE_T, ARRAY_T, STRING_ARRAY_T, STRING_T, SCALAR_CHAR_T, SCALAR_BOOL_T, SCALAR_SHORT_T, SCALAR_INT_T, SCALAR_LONG_INT_T,
SCALAR_FLOAT_T, SCALAR_DOUBLE_T,
SCALAR_CMPLX_FLOAT_T, SCALAR_CMPLX_DOUBLE_T, EXTERNAL_T, UNKNOWN_T} paramType;
#ifndef IN_BIT
#define IN_BIT 16
#endif
#ifndef OUT_BIT
#define OUT_BIT 256
#endif
struct FuncParam
{
FuncParam() { countOfPars = 0; }
void init(const int numPar)
{
countOfPars = numPar;
if (numPar)
{
parameters.resize(numPar);
parametersT.resize(numPar);
inout_types.resize(numPar);
std::fill(parametersT.begin(), parametersT.end(), NONE_T);
std::fill(inout_types.begin(), inout_types.end(), 0);
}
}
void completeParams()
{
for (int z = 0; z < countOfPars; ++z)
if (inout_types[z] == 0)
inout_types[z] = IN_BIT;
}
bool isArgIn(const int num) const
{
if (num >= countOfPars)
return false;
else
return (inout_types[num] & IN_BIT) != 0;
}
bool isArgOut(const int num) const
{
if (num >= countOfPars)
return false;
else
return (inout_types[num] & OUT_BIT) != 0;
}
bool isArgInOut(const int num) const
{
if (num >= countOfPars)
return false;
else
return isArgIn(num) && isArgOut(num);
}
static bool isArgIn(int64_t type) { return (type & IN_BIT) != 0; }
static bool isArgOut(int64_t type) { return (type & OUT_BIT) != 0; }
static bool isArgInOut(int64_t type) { return isArgIn(type) && isArgOut(type); }
std::vector<std::string> identificators;
std::vector<void*> parameters;
std::vector<paramType> parametersT;
std::vector<int> inout_types;
int countOfPars;
};
#ifndef IN_BIT
#undef IN_BIT
#endif
#ifndef OUT_BIT
#undef OUT_BIT
#endif
struct NestedFuncCall
{
std::string CalledFuncName;
std::vector<std::vector<int>> NoOfParamUsedForCall;
NestedFuncCall(std::string funcName) : CalledFuncName(funcName) { }
NestedFuncCall(std::string funcName, int ParsNum) :
CalledFuncName(funcName),
NoOfParamUsedForCall(std::vector<std::vector<int>>(ParsNum))
{ }
};
struct FuncInfoCallFrom {
// <name, line>
std::pair<std::string, int> detailCallsFrom;
// <pointer, SG_VAR> SgStatement for PROC_STAT, SgExpression for FUNC_CALL, VAR_REF for external calls
std::pair<void*, int> pointerDetailCallsFrom;
// parent SgStatement* of FUNC_CALL
void* parentForPointer;
FuncParam actualParams;
};
struct FuncInfo
{
std::string funcName;
std::pair<int, int> linesNum;
std::string fileName;
Statement *funcPointer;
bool isMain;
bool isInterface;
std::set<std::string> callsFrom; //calls from this function
std::set<FuncInfo*> callsFromV;
std::vector<FuncInfoCallFrom> callsFromDetailed;
std::map<std::string, std::set<std::string>> commonBlocks;
std::vector<FuncInfo*> callsTo; //calls of this function
FuncParam funcParams;
std::vector<bool> isParamUsedAsIndex;
std::vector<NestedFuncCall> funcsCalledFromThis; // size = amount of calls in this func;
// if (FuncsCalledFromThis[func_call_idx].
// NoOfParamUsedForCall.size() == 0) - no params of cur func used
ShadowNode* shadowTreeStart;
ShadowNode* shadowTreeEnd;
std::map<void*, ShadowNode*> allShadowNodes;
std::set<DIST::Array*> allUsedArrays; // real array refs
std::set<DIST::Array*> usedArraysWrite; // real array refs
std::vector<LoopGraph*> loopsInFunc;
std::set<int> linesOfIO;
std::set<int> linesOfStop;
std::map<std::string, FuncInfo*> interfaceBlocks;
std::map<std::string, FuncInfo*> interfaceSynonims;
std::vector<FuncInfo*> entry; // all entry points
std::set<std::string> externalCalls;
bool isPure; // does this func or funcs called from this have common block[s] and have no side effects
bool doNotInline;
bool doNotAnalyze;
bool needToInline;
bool deadFunction;
// for RESOLVE_PAR_REGIONS
int inRegion; // 0 - none, 1 - explicit, 2 - implicit, 3 - indirect
std::set<uint64_t> callRegions; // 0 - default; forall i > 0, i - user region
bool isInRegion() { return inRegion == 1 || inRegion == 2; }
bool isIndirect() { return inRegion == 3; }
//
std::vector<FuncInfo*> fullCopiesOfThisFunction;
FuncInfo() :
doNotInline(false), funcPointer(NULL), doNotAnalyze(false), needToInline(false),
deadFunction(false), inRegion(0), isPure(false), isMain(false), shadowTreeStart(NULL), shadowTreeEnd(NULL),
isInterface(false) { }
FuncInfo(const std::string &funcName, const std::pair<int, int> &lineNum) :
funcName(funcName), linesNum(lineNum), doNotInline(false), funcPointer(NULL),
doNotAnalyze(false), needToInline(false), deadFunction(false), inRegion(0), isMain(false),
isPure(false), shadowTreeStart(NULL), shadowTreeEnd(NULL), isInterface(false) { }
#if !__SPC
FuncInfo(const std::string &funcName, const std::pair<int, int> &lineNum, Statement *pointer) :
funcName(funcName), linesNum(lineNum), doNotInline(false), funcPointer(pointer),
doNotAnalyze(false), needToInline(false), deadFunction(false), inRegion(0), isMain(false),
isPure(false), shadowTreeStart(NULL), shadowTreeEnd(NULL), isInterface(false) { fileName = pointer->fileName(); }
#endif
std::vector<std::pair<void*, int>> GetDetailedCallInfo(const std::string &funcName)
{
std::vector<std::pair<void*, int>> result;
for (int i = 0; i < callsFromDetailed.size(); ++i)
{
if (callsFromDetailed[i].detailCallsFrom.first == funcName)
result.push_back(callsFromDetailed[i].pointerDetailCallsFrom);
}
return result;
}
std::string getFuncNameWithContainsByRegion(const uint64_t regionId)
{
if (regionId && callRegions.size() > 1 && callRegions.find(regionId) != callRegions.end())
return funcName + "_r" + std::to_string(regionId);
return funcName;
}
std::string getFuncNameByRegion(const std::string &shortName, const uint64_t regionId)
{
if (regionId && callRegions.size() > 1 && callRegions.find(regionId) != callRegions.end())
return shortName + "_r" + std::to_string(regionId);
return shortName;
}
void removeNonDistrArrays()
{
std::set<DIST::Array*> newUsedArrays;
for (auto &elem : allUsedArrays)
if (elem->GetDistributeFlagVal() == DIST::DISTR)
newUsedArrays.insert(elem);
allUsedArrays = newUsedArrays;
}
bool usesIO() const { return (linesOfIO.size() != 0 || linesOfStop.size() != 0); }
std::string getCallName(const std::pair<void*, int>& call_info, const std::string& name, int line)
{
if (line <= 0)
return name;
std::set<std::string> names;
for (auto& call : callsFromDetailed)
{
if (call.pointerDetailCallsFrom == call_info && call.detailCallsFrom.second == line)
return call.detailCallsFrom.first;
if (call.detailCallsFrom.second == line)
if (call.detailCallsFrom.first.find(name) != std::string::npos)
names.insert(call.detailCallsFrom.first);
}
//TODO: detect func call better
if (names.size() == 1)
return *names.begin();
//try to find in next lvl calls
for (auto& call : callsFromDetailed)
{
if (call.detailCallsFrom.second == line)
{
std::string name_next = call.detailCallsFrom.first;
std::set<FuncInfo*> next, done;
for (auto& callFrom : callsFromV)
if (callFrom->funcName == name_next)
next.insert(callFrom);
done = next;
while (next.size())
{
auto curr = next;
next.clear();
for (auto& callFrom : curr)
{
for (auto& call : callFrom->callsFromDetailed)
{
if (call.detailCallsFrom.first == name)
return call.detailCallsFrom.first;
}
for (auto& callFromNext : callFrom->callsFromV)
{
if (done.find(callFromNext) == done.end())
{
next.insert(callFromNext);
done.insert(callFromNext);
}
}
}
}
}
}
return "";
}
};
struct CallV
{
std::string fName;
std::string fileName;
bool isMain;
int inRegion;
CallV() : inRegion(0), isMain(false) { }
CallV(const std::string &fName) :
fName(fName), fileName(""), isMain(false), inRegion(0)
{ }
CallV(const std::string &fName, const std::string &fileName, bool isMain) :
fName(fName), fileName(fileName), isMain(isMain), inRegion(0)
{ }
std::string to_string()
{
return fName + "@" + fileName + "@" + (isMain ? "1" : "0") + "@" + std::to_string(inRegion);
}
};
void propagateArrayFlags(const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays, std::map<std::string, std::vector<Messages>> &SPF_messages);
void removeDistrStateFromDeadFunctions(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays);
bool detectMpiCalls(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, std::map<std::string, std::vector<Messages>>& SPF_messages);
int getLvlCall(FuncInfo* currF, int lvl, const std::string& func, const std::string& file, int line);
void compliteArrayUsage(DIST::Arrays<int>& allArraysForRegion, std::map<std::tuple<int, std::string, std::string>, DIST::Array*>& createdArrays, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, const std::map<DIST::Array*, std::tuple<int, std::string, std::string>>& tableOfUniqNamesByArray);
void remoteNotUsedArrays(std::map<std::tuple<int, std::string, std::string>, DIST::Array*>& createdArrays, const std::set<DIST::Array*>& usedArraysAcrossRegions, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);

View File

@@ -0,0 +1,981 @@
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <map>
#include <vector>
#include <set>
#include <string>
#include "../Utils/errors.h"
#include "graph_calls.h"
#include "../Distribution/Distribution.h"
#include "../Utils/utils.h"
#include "../ParallelizationRegions/ParRegions.h"
using std::vector;
using std::map;
using std::string;
using std::wstring;
using std::set;
using std::to_string;
using std::tuple;
using std::pair;
#define DEB 0
void createMapOfFunc(const vector<FuncInfo*> &allFuncInfo, map<pair<string, int>, FuncInfo*> &mapFuncInfo)
{
for (auto &func : allFuncInfo)
mapFuncInfo[make_pair(func->fileName, func->linesNum.first)] = func;
}
void createMapOfFunc(const vector<FuncInfo*> &allFuncInfo, map<string, FuncInfo*> &mapFuncInfo)
{
for (auto &func : allFuncInfo)
mapFuncInfo[func->funcName] = func;
}
void createMapOfFunc(const map<string, vector<FuncInfo*>> &allFuncInfo, map<string, FuncInfo*> &mapFuncInfo)
{
for (auto it = allFuncInfo.begin(); it != allFuncInfo.end(); ++it)
for (int k = 0; k < it->second.size(); ++k)
mapFuncInfo[it->second[k]->funcName] = it->second[k];
}
FuncInfo* getFuncInfo(const map<string, FuncInfo*> &funcMap, const string &funcName)
{
auto it = funcMap.find(funcName);
if (it == funcMap.end())
return NULL;
return it->second;
}
string removeString(const string &toRemove, const string &inStr)
{
string outStr(inStr);
const size_t found = outStr.find(toRemove);
if (found != string::npos)
outStr.erase(found, toRemove.length());
return outStr;
}
void updateFuncInfo(const map<string, vector<FuncInfo*>> &allFuncInfo) // const here
{
bool changesDone = false;
map<string, FuncInfo*> mapFuncInfo;
createMapOfFunc(allFuncInfo, mapFuncInfo);
do
{
changesDone = false;
for (auto &it : mapFuncInfo)
{
FuncInfo *currInfo = it.second;
for(auto &funcCall : currInfo->funcsCalledFromThis)
{
// Find pointer to info of called function
auto itCalledFunc = mapFuncInfo.find(funcCall.CalledFuncName);
if (itCalledFunc != mapFuncInfo.end() && !itCalledFunc->second->isInterface)
{
FuncInfo *calledFunc = itCalledFunc->second;
// check for pureness
if (!calledFunc->isPure && currInfo->isPure)
{
currInfo->isPure = false;
changesDone = true;
}
// check for using parameter as index
// Iterate through all pars of the call
for (int parNo = 0; parNo < funcCall.NoOfParamUsedForCall.size(); ++parNo)
{
auto& parOfCalled = funcCall.NoOfParamUsedForCall[parNo];
// If this par of called func is used as index change
if (calledFunc->isParamUsedAsIndex[parNo])
{
// Then pars of calling func which are used in this par of called
// are also used as index
for (auto &parOfCalling : parOfCalled)
{
if (!currInfo->isParamUsedAsIndex[parOfCalling])
{
changesDone = true;
currInfo->isParamUsedAsIndex[parOfCalling] = true;
}
}
}
}
// propagate inout types
for (int parNo = 0; parNo < funcCall.NoOfParamUsedForCall.size(); ++parNo)
{
auto& parOfCalled = funcCall.NoOfParamUsedForCall[parNo];
if (parOfCalled.size() == 0)
continue;
if (calledFunc->funcParams.isArgOut(parNo))
{
for (auto& num : parOfCalled)
{
if (!currInfo->funcParams.isArgOut(num))
{
currInfo->funcParams.inout_types[num] |= OUT_BIT;
changesDone = true;
}
}
}
if (calledFunc->funcParams.isArgIn(parNo))
{
for (auto& num : parOfCalled)
{
if (!currInfo->funcParams.isArgIn(num))
{
currInfo->funcParams.inout_types[num] |= IN_BIT;
changesDone = true;
}
}
}
}
}
}
}
} while (changesDone);
// check for io usage
do
{
changesDone = false;
for (auto &it : mapFuncInfo)
{
FuncInfo *currInfo = it.second;
for (auto &callInfo : currInfo->callsFromDetailed)
{
auto& funcCall = callInfo.detailCallsFrom;
auto itCalledFunc = mapFuncInfo.find(funcCall.first);
if (itCalledFunc != mapFuncInfo.end())
{
FuncInfo *calledFunc = itCalledFunc->second;
if (calledFunc->linesOfIO.size())
{
const int lineOfCall = funcCall.second;
auto it = currInfo->linesOfIO.find(lineOfCall);
if (it == currInfo->linesOfIO.end())
{
currInfo->linesOfIO.insert(lineOfCall);
changesDone = true;
}
}
}
}
}
} while (changesDone);
//fill all pars IN, if they have NONE status
for (auto& it : mapFuncInfo)
{
FuncInfo* currInfo = it.second;
currInfo->funcParams.completeParams();
}
}
int CreateCallGraphViz(const char *fileName, const map<string, vector<FuncInfo*>> &funcByFile, map<string, CallV> &V, vector<string> &E)
{
map<string, FuncInfo*> allFuncs;
createMapOfFunc(funcByFile, allFuncs);
string graph = "";
graph += "digraph G{\n";
auto it = funcByFile.begin();
int fileNum = 0;
set<string> inCluster;
set<string> unknownCluster;
char buf[1024];
while (it != funcByFile.end())
{
sprintf(buf, "subgraph cluster%d {\n", fileNum);
graph += buf;
const int dimSize = (int)it->second.size();
set<string> uniqNames;
for (int k = 0; k < dimSize; ++k)
{
const string currfunc = it->second[k]->funcName;
auto it = uniqNames.find(currfunc);
if (it == uniqNames.end())
{
uniqNames.insert(it, currfunc);
inCluster.insert(currfunc);
sprintf(buf, "\"%s\"\n", currfunc.c_str());
graph += buf;
}
}
sprintf(buf, "label = \"file <%s>\"\n", removeString(".\\", it->first).c_str());
graph += buf;
graph += "}\n";
fileNum++;
it++;
}
it = funcByFile.begin();
while (it != funcByFile.end())
{
const char *formatString = "\"%s\" -> \"%s\" [minlen=2.0];\n";
const int dimSize = (int)it->second.size();
for (int k = 0; k < dimSize; ++k)
{
const string &callFrom = it->second[k]->funcName;
const FuncInfo *callFromP = it->second[k];
for (auto &callItem : it->second[k]->callsFrom)
{
sprintf(buf, formatString, callFrom.c_str(), callItem.c_str());
graph += buf;
if (inCluster.find(callFrom) == inCluster.end())
unknownCluster.insert(callFrom);
if (inCluster.find(callItem) == inCluster.end())
unknownCluster.insert(callItem);
if (V.find(callFrom) == V.end())
{
V[callFrom] = CallV(callFromP->funcName, callFromP->fileName, callFromP->isMain);
V[callFrom].inRegion = callFromP->inRegion;
}
if (V.find(callItem) == V.end())
{
auto it = allFuncs.find(callItem);
if (it == allFuncs.end())
V[callItem] = CallV(callItem);
else
{
auto currF = it->second;
V[callItem] = CallV(callItem, currF->fileName, currF->isMain);
V[callItem].inRegion = currF->inRegion;
}
}
E.push_back(callFrom);
E.push_back(callItem);
}
}
it++;
}
if (unknownCluster.size() > 0)
{
sprintf(buf, "subgraph cluster%d {\n", fileNum);
graph += buf;
for (auto &func : unknownCluster)
{
sprintf(buf, "\"%s\"\n", func.c_str());
graph += buf;
}
sprintf(buf, "label = \"file <UNKNOWN>\"\n");
graph += buf;
graph += "}\n";
}
graph += "overlap=false\n";
graph += "}\n";
if (fileName)
{
FILE *out = fopen(fileName, "w");
if (out == NULL)
{
__spf_print(1, "can not open file %s\n", fileName);
return -1;
}
fprintf(out, graph.c_str());
fclose(out);
}
return 0;
}
int CreateFuncInfo(const char *fileName, const map<string, vector<FuncInfo*>> &funcByFile)
{
string funcOut = "";
for (auto &byFile : funcByFile)
{
funcOut += "FILE " + byFile.first + ":\n";
for (auto &func : byFile.second)
{
funcOut += (func->isInterface ? ("INTERFACE OF ") : "") + string(" FUNCTION '") +
func->funcName + "' " + (func->isPure ? " is PURE" : "is IMPURE") + "\n";
char buf[256];
sprintf(buf, " LINES [%d, %d] \n", func->linesNum.first, func->linesNum.second);
funcOut += buf;
sprintf(buf, " PARAMETERS %d:\n", func->funcParams.countOfPars);
funcOut += buf;
for (int z = 0; z < func->funcParams.countOfPars; ++z)
{
bool in = func->funcParams.isArgIn(z);
bool out = func->funcParams.isArgOut(z);
const char *inout = "";
if (in && out)
inout = "IN/OUT";
else if (in)
inout = "IN";
else if (out)
inout = "OUT";
sprintf(buf, " %s: type '%s', %s\n", func->funcParams.identificators[z].c_str(),
paramNames[func->funcParams.parametersT[z]],
inout);
funcOut += buf;
}
}
}
if (fileName)
{
FILE *out = fopen(fileName, "w");
if (out == NULL)
{
__spf_print(1, "can not open file %s\n", fileName);
return -1;
}
fprintf(out, funcOut.c_str());
fclose(out);
}
return 0;
}
extern map<string, vector<FuncInfo*>> allFuncInfo; // file -> Info
FuncInfo* isUserFunctionInProject(const string &func)
{
FuncInfo *ret = NULL;
for (auto &it : allFuncInfo)
{
for (auto &currF : it.second)
{
if (currF->funcName == func)
{
ret = currF;
break;
}
}
if (ret)
break;
}
return ret;
}
string convertToString(const FuncInfo *currFunc)
{
string result = "";
if (currFunc)
{
result += "|" + currFunc->funcName + "|" + to_string(currFunc->linesNum.first) +
"#" + to_string(currFunc->linesNum.second) +
"#" + to_string(currFunc->callsFromDetailed.size()) +
"#" + to_string(currFunc->needToInline) + "#" + to_string(currFunc->doNotInline) +
"#" + to_string(currFunc->doNotAnalyze) + "#" + to_string((int)currFunc->isMain);
result += "#" + to_string(currFunc->funcParams.countOfPars);
if (currFunc->funcParams.countOfPars)
{
for (int z = 0; z < currFunc->funcParams.countOfPars; ++z)
{
result += "#" + currFunc->funcParams.identificators[z] + "#" + to_string(currFunc->funcParams.inout_types[z]);
result += "#" + string(paramNames[currFunc->funcParams.parametersT[z]]);
}
}
for (int i = 0; i < currFunc->callsFromDetailed.size(); ++i)
result += "|" + currFunc->callsFromDetailed[i].detailCallsFrom.first + "|" + to_string(currFunc->callsFromDetailed[i].detailCallsFrom.second);
}
return result;
}
// Find dead functions and fill callTo / callFrom information
void findDeadFunctionsAndFillCalls(map<string, vector<FuncInfo*>> &allFuncInfo, map<string, vector<Messages>> &allMessages, bool noPrint)
{
map<string, FuncInfo*> mapFuncInfo;
createMapOfFunc(allFuncInfo, mapFuncInfo);
set<string> allExternalCalls;
set<string> allChildCalls;
for (auto &it : mapFuncInfo)
{
FuncInfo *currInfo = it.second;
allChildCalls.insert(currInfo->callsFrom.begin(), currInfo->callsFrom.end());
allExternalCalls.insert(currInfo->externalCalls.begin(), currInfo->externalCalls.end());
}
for (auto &it : mapFuncInfo)
{
FuncInfo *currInfo = it.second;
if (allChildCalls.find(it.first) == allChildCalls.end())
if (!currInfo->isMain && allExternalCalls.find(currInfo->funcName) == allExternalCalls.end())
currInfo->deadFunction = currInfo->doNotAnalyze = true;
}
if (!noPrint)
{
for (auto &it : allFuncInfo)
{
const string &currF = it.first;
auto itM = allMessages.find(currF);
if (itM == allMessages.end())
itM = allMessages.insert(itM, make_pair(currF, vector<Messages>()));
for (auto& func : it.second)
if (func->deadFunction)
itM->second.push_back(Messages(WARR, func->linesNum.first, R47, L"This function is not called in current project", 1015));
}
}
for (auto &it : mapFuncInfo)
{
FuncInfo *currInfo = it.second;
for (auto &k : currInfo->callsFrom)
{
auto itFound = mapFuncInfo.find(k);
if (itFound != mapFuncInfo.end())
{
FuncInfo *callFrom = itFound->second;
callFrom->callsTo.push_back(currInfo);
currInfo->callsFromV.insert(callFrom);
}
}
}
FuncInfo* main = NULL;
for (auto& it : mapFuncInfo)
if (it.second->isMain)
main = it.second;
checkNull(main, convertFileName(__FILE__).c_str(), __LINE__);
set<FuncInfo*> liveFunctions;
liveFunctions.insert(main);
for (auto& callFrom : main->callsFromV)
liveFunctions.insert(callFrom);
//find live functions
bool changes = true;
while (changes)
{
changes = false;
for (auto& currInfo : liveFunctions)
{
for (auto& callFrom : currInfo->callsFromV) {
if (liveFunctions.find(callFrom) == liveFunctions.end()) {
changes = true;
liveFunctions.insert(callFrom);
}
}
}
}
// propagate 'deadFunction' status for all 'CallsFrom' from dead functions
changes = true;
while (changes)
{
changes = false;
for (auto& it : mapFuncInfo)
{
FuncInfo* currInfo = it.second;
if (currInfo->deadFunction == false)
continue;
for (auto& callFrom : currInfo->callsFrom)
{
auto itFrom = mapFuncInfo.find(callFrom);
if (itFrom != mapFuncInfo.end())
{
auto func = itFrom->second;
if (!func->deadFunction && liveFunctions.find(func) == liveFunctions.end())
{
changes = true;
func->deadFunction = func->doNotAnalyze = true;
}
}
}
}
}
}
static inline void addLinks(const FuncParam &actual, const FuncParam &formal, map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
{
if (actual.parameters.size() != formal.parameters.size())
return;
else
{
for (int i = 0; i < actual.parameters.size(); ++i)
if (actual.parametersT[i] == formal.parametersT[i] && formal.parametersT[i] == ARRAY_T)
{
//printf("add lhs %s -> rhs %s\n", ((DIST::Array*)formal.parameters[i])->GetName().c_str(), ((DIST::Array*)actual.parameters[i])->GetName().c_str());
if (((DIST::Array*)formal.parameters[i]) == ((DIST::Array*)actual.parameters[i]))
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
arrayLinksByFuncCalls[(DIST::Array*)formal.parameters[i]].insert((DIST::Array*)actual.parameters[i]);
}
}
}
static bool propagateUp(DIST::Array *from, set<DIST::Array*> to, DIST::distFlag flag, bool &change, map<string, vector<Messages>> &SPF_messages)
{
bool globalChange = false;
if (from->GetDistributeFlagVal() == flag)
{
for (auto &realRef : to)
{
auto val = realRef->GetDistributeFlagVal();
if (val != flag)
{
//exclude this case
if (flag == DIST::IO_PRIV && val == DIST::SPF_PRIV ||
flag == DIST::NO_DISTR && val == DIST::SPF_PRIV ||
flag == DIST::NO_DISTR && val == DIST::IO_PRIV)
;
else
{
realRef->SetDistributeFlag(flag);
if (flag == DIST::IO_PRIV)
{
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of DVM's I/O constraints", to_wstring(realRef->GetShortName()).c_str());
__spf_printToLongBuf(messageR, R68, to_wstring(realRef->GetShortName()).c_str());
auto places = realRef->GetDeclInfo();
for (auto& place : places)
getObjectForFileFromMap(place.first.c_str(), SPF_messages).push_back(Messages(WARR, place.second, messageR, messageE, 1037));
}
#if DEB
printf("up: set %d %s\n", flag, realRef->GetName().c_str());
#endif
change = true;
globalChange = true;
}
}
}
}
return globalChange;
}
static bool propagateFlag(bool isDown, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
map<string, vector<Messages>> &SPF_messages)
{
bool globalChange = false;
bool change = true;
while (change)
{
change = false;
for (auto &array : declaredArrays)
{
set<DIST::Array*> realArrayRefs;
getRealArrayRefs(array.second.first, array.second.first, realArrayRefs, arrayLinksByFuncCalls);
bool allNonDistr = true;
bool allDistr = true;
bool nonDistrSpfPriv = false;
bool nonDistrIOPriv = false;
bool init = false;
// propagate SPF to down calls
for (auto &realRef : realArrayRefs)
{
if (realRef != array.second.first)
{
bool nonDistr = realRef->IsNotDistribute();
if (realRef->GetDistributeFlagVal() == DIST::SPF_PRIV)
nonDistrSpfPriv = true;
else if (realRef->GetDistributeFlagVal() == DIST::IO_PRIV)
nonDistrIOPriv = true;
allNonDistr = allNonDistr && nonDistr;
allDistr = allDistr && !nonDistr;
init = true;
}
}
if (init)
{
if (allNonDistr && array.second.first->IsNotDistribute() == false)
{
if (isDown)
{
if (nonDistrSpfPriv)
{
array.second.first->SetDistributeFlag(DIST::SPF_PRIV);
if (DEB)
printf("down: set %d %s\n", DIST::SPF_PRIV, array.second.first->GetName().c_str());
}
else if (nonDistrIOPriv)
{
array.second.first->SetDistributeFlag(DIST::IO_PRIV);
if (DEB)
printf("down: set %d %s\n", DIST::IO_PRIV, array.second.first->GetName().c_str());
}
else
{
array.second.first->SetDistributeFlag(DIST::NO_DISTR);
if (DEB)
printf("down: set %d %s\n", DIST::NO_DISTR, array.second.first->GetName().c_str());
}
change = true;
globalChange = true;
}
}
else
{
if (!isDown)
{
bool ret = propagateUp(array.second.first, realArrayRefs, DIST::SPF_PRIV, change, SPF_messages);
globalChange = globalChange || ret;
ret = propagateUp(array.second.first, realArrayRefs, DIST::IO_PRIV, change, SPF_messages);
globalChange = globalChange || ret;
ret = propagateUp(array.second.first, realArrayRefs, DIST::NO_DISTR, change, SPF_messages);
globalChange = globalChange || ret;
}
}
}
}
}
return globalChange;
}
void propagateArrayFlags(const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
map<string, vector<Messages>> &SPF_messages)
{
bool change = true;
while (change)
{
bool changeD = propagateFlag(true, arrayLinksByFuncCalls, declaredArrays, SPF_messages);
bool changeU = propagateFlag(false, arrayLinksByFuncCalls, declaredArrays, SPF_messages);
change = changeD || changeU;
}
}
static void aggregateUsedArrays(map<string, FuncInfo*> &funcByName, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
{
//change to real refs
for (auto &func : funcByName)
{
{
set<DIST::Array*> curr = func.second->allUsedArrays;
set<DIST::Array*> newRefs;
for (auto &array : curr)
getRealArrayRefs(array, array, newRefs, arrayLinksByFuncCalls);
func.second->allUsedArrays.clear();
for (auto &newArray : newRefs)
if (newArray->IsNotDistribute() == false)
func.second->allUsedArrays.insert(newArray);
}
{
set<DIST::Array*> curr = func.second->usedArraysWrite;
set<DIST::Array*> newRefs;
for (auto &array : curr)
getRealArrayRefs(array, array, newRefs, arrayLinksByFuncCalls);
func.second->usedArraysWrite.clear();
for (auto &newArray : newRefs)
if (newArray->IsNotDistribute() == false)
func.second->usedArraysWrite.insert(newArray);
}
}
bool changed = true;
while (changed)
{
changed = false;
for (auto &func : funcByName)
{
for (auto &callsFrom : func.second->callsFrom)
{
auto itF = funcByName.find(callsFrom);
if (itF != funcByName.end())
{
for (auto &usedArray : itF->second->allUsedArrays)
{
auto itA = func.second->allUsedArrays.find(usedArray);
if (itA == func.second->allUsedArrays.end())
{
changed = true;
func.second->allUsedArrays.insert(usedArray);
}
}
}
}
}
}
changed = true;
while (changed)
{
changed = false;
for (auto &func : funcByName)
{
for (auto &callsFrom : func.second->callsFrom)
{
auto itF = funcByName.find(callsFrom);
if (itF != funcByName.end())
{
for (auto &usedArray : itF->second->usedArraysWrite)
{
auto itA = func.second->usedArraysWrite.find(usedArray);
if (itA == func.second->usedArraysWrite.end())
{
changed = true;
func.second->usedArraysWrite.insert(usedArray);
}
}
}
}
}
}
}
void createLinksBetweenFormalAndActualParams(map<string, vector<FuncInfo*>> &allFuncInfo, map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
map<string, vector<Messages>> &SPF_messages, bool keepFiles)
{
for (auto &funcsOnFile : allFuncInfo)
{
for (auto &func : funcsOnFile.second)
{
//printf("func %s :\n", func->funcName.c_str());
const string &name = func->funcName;
for (auto &caller : func->callsTo)
for (int i = 0; i < caller->callsFromDetailed.size(); ++i)
if (caller->callsFromDetailed[i].detailCallsFrom.first == name)
addLinks(caller->callsFromDetailed[i].actualParams, func->funcParams, arrayLinksByFuncCalls);
}
}
#if DEB
printf("BEFORE\n");
//debug dump
for (auto& elem : declaredArrays)
{
auto array = elem.second.first;
auto flag = array->GetDistributeFlagVal();
// int { DISTR = 0, NO_DISTR, SPF_PRIV, IO_PRIV } distFlagType;
string flagS = "";
if (flag == DIST::DISTR)
flagS = "DISTR";
else if (flag == DIST::NO_DISTR)
flagS = "NO_DISTR";
else if (flag == DIST::SPF_PRIV)
flagS = "SPF_PRIV";
else if (flag == DIST::IO_PRIV)
flagS = "IO_PRIV";
printf("%s %s flag %s\n", array->GetShortName(), array->GetName(), flagS.c_str());
}
#endif
if (keepFiles)
{
FILE *file = fopen("_arrayLinksByCalls.txt", "w");
for (auto &elem : arrayLinksByFuncCalls)
{
fprintf(file, "%s -> ", elem.first->GetName().c_str());
for (auto &rhs : elem.second)
fprintf(file, " %s ", rhs->GetName().c_str());
fprintf(file, "\n");
}
fclose(file);
}
propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages);
//propagate distr state
bool change = true;
while (change)
{
change = false;
for (auto &array : declaredArrays)
{
set<DIST::Array*> realArrayRefs;
getRealArrayRefs(array.second.first, array.second.first, realArrayRefs, arrayLinksByFuncCalls);
if (realArrayRefs.size() && (*realArrayRefs.begin()) != array.second.first &&
!(*realArrayRefs.begin())->IsNotDistribute() && array.second.first->IsNotDistribute())
{
array.second.first->SetDistributeFlag(DIST::DISTR);
change = true;
}
}
}
map<string, FuncInfo*> funcByName;
createMapOfFunc(allFuncInfo, funcByName);
aggregateUsedArrays(funcByName, arrayLinksByFuncCalls);
#if DEB
printf("AFTER\n");
//debug dump
for (auto &elem : declaredArrays)
{
auto array = elem.second.first;
auto flag = array->GetDistributeFlagVal();
// int { DISTR = 0, NO_DISTR, SPF_PRIV, IO_PRIV } distFlagType;
string flagS = "";
if (flag == DIST::DISTR)
flagS = "DISTR";
else if (flag == DIST::NO_DISTR)
flagS = "NO_DISTR";
else if (flag == DIST::SPF_PRIV)
flagS = "SPF_PRIV";
else if (flag == DIST::IO_PRIV)
flagS = "IO_PRIV";
printf("%s %s flag %s\n", array->GetShortName(), array->GetName(), flagS.c_str());
}
printf("");
#endif
}
bool detectMpiCalls(const map<string, vector<FuncInfo*>>& allFuncInfo, map<string, vector<Messages>>& SPF_messages)
{
bool retVal = false;
map<string, FuncInfo*> funcByName;
createMapOfFunc(allFuncInfo, funcByName);
for (auto& byFile : allFuncInfo)
{
for (auto& func : byFile.second)
{
for (auto& callInfo: func->callsFromDetailed)
{
auto& callsFromThis = callInfo.detailCallsFrom;
if (isMpiFunction(callsFromThis.first) && funcByName.find(callsFromThis.first) == funcByName.end())
{
retVal = true;
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Detected mpi call, turn on special regime of paralyzing");
__spf_printToLongBuf(messageR, R148);
SPF_messages[byFile.first].push_back(Messages(NOTE, callsFromThis.second, messageR, messageE, 1051));
}
}
}
}
return retVal;
}
void excludeArraysFromDistribution(const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> declaredArrays,
map<string, vector<LoopGraph*>>& loopGraph,
vector<ParallelRegion*> parallelRegions,
map<string, vector<Messages>>& SPF_messages,
map<tuple<int, string, string>, DIST::Array*>& createdArrays,
int sharedMemoryParallelization)
{
checkArraysMapping(loopGraph, SPF_messages, arrayLinksByFuncCalls);
propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages);
if (sharedMemoryParallelization == 0)
{
for (int z = 0; z < parallelRegions.size(); ++z)
filterArrayInCSRGraph(loopGraph, allFuncInfo, parallelRegions[z], arrayLinksByFuncCalls, SPF_messages);
propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages);
}
for (auto& loopByFile : loopGraph)
{
for (auto& loop : loopByFile.second)
{
loop->removeNonDistrArrays();
loop->removeGraphData();
}
}
for (auto& funcByFile : allFuncInfo)
for (auto& func : funcByFile.second)
func->removeNonDistrArrays();
//restore
for (int z = 0; z < parallelRegions.size(); ++z)
{
parallelRegions[z]->GetAllArraysToModify().cleanData();
parallelRegions[z]->GetGraphToModify().ClearGraphCSR();
parallelRegions[z]->GetReducedGraphToModify().ClearGraphCSR();
}
createdArrays.clear();
}
void compliteArrayUsage(DIST::Arrays<int>& allArraysForRegion,
map<tuple<int, string, string>, DIST::Array*>& createdArrays,
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
const map<DIST::Array*, tuple<int, string, string>>& tableOfUniqNamesByArray)
{
set<DIST::Array*> usedArraysLocal;
usedArraysLocal.insert(allArraysForRegion.GetArrays().begin(), allArraysForRegion.GetArrays().end());
//add array that linked with used
for (auto& used : usedArraysLocal)
{
set<DIST::Array*> allArrayRefs;
getAllArrayRefs(used, used, allArrayRefs, arrayLinksByFuncCalls);
for (auto& array : allArrayRefs)
{
if (usedArraysLocal.find(array) == usedArraysLocal.end())
{
auto key = tableOfUniqNamesByArray.find(array);
if (key != tableOfUniqNamesByArray.end())
{
createdArrays.insert(make_pair(key->second, key->first));
allArraysForRegion.AddArrayToGraph(array);
}
}
}
}
}
void remoteNotUsedArrays(map<tuple<int, string, string>, DIST::Array*>& createdArrays,
const set<DIST::Array*>& usedArraysAcrossRegions,
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
{
//remove arrays that is not used
map<tuple<int, string, string>, DIST::Array*> createdArraysNew;
for (auto it = createdArrays.begin(); it != createdArrays.end(); ++it)
{
if (usedArraysAcrossRegions.find(it->second) != usedArraysAcrossRegions.end())
createdArraysNew.insert(*it);
else
{
set<DIST::Array*> realArrayRefs;
getRealArrayRefs(it->second, it->second, realArrayRefs, arrayLinksByFuncCalls);
for (auto& array : realArrayRefs)
{
if (array == it->second)
continue;
if (usedArraysAcrossRegions.find(array) != usedArraysAcrossRegions.end())
createdArraysNew.insert(*it);
}
}
}
createdArrays = createdArraysNew;
}

View File

@@ -0,0 +1,57 @@
#pragma once
#include <string>
#include <map>
#include <vector>
#include <set>
#include "graph_calls.h"
#include "../GraphLoop/graph_loops.h"
#include "../ParallelizationRegions/ParRegions.h"
namespace Distribution
{
class ArrayAccessInfo;
}
namespace DIST = Distribution;
namespace SAPFOR
{
class BasicBlock;
}
int CreateCallGraphViz(const char *fileName, const std::map<std::string, std::vector<FuncInfo*>> &funcByFile, std::map<std::string, CallV> &V, std::vector<std::string> &E);
int CreateFuncInfo(const char *fileName, const std::map<std::string, std::vector<FuncInfo*>> &funcByFile);
std::string removeString(const std::string &toRemove, const std::string &inStr);
FuncInfo* isUserFunctionInProject(const std::string &func);
std::string convertToString(const FuncInfo *currFunc);
void findDeadFunctionsAndFillCalls(std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, std::map<std::string, std::vector<Messages>> &allMessages, bool noPrint = false);
void createLinksBetweenFormalAndActualParams(std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls,
const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
std::map<std::string, std::vector<Messages>> &SPF_messages, bool keepFiles = false);
void createMapOfFunc(const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, std::map<std::string, FuncInfo*> &mapFuncInfo);
void createMapOfFunc(const std::vector<FuncInfo*> &allFuncInfo, std::map<std::string, FuncInfo*> &mapFuncInfo);
void createMapOfFunc(const std::vector<FuncInfo*> &allFuncInfo, std::map<std::pair<std::string, int>, FuncInfo*> &mapFuncInfo);
FuncInfo* getFuncInfo(const std::map<std::string, FuncInfo*> &funcMap, const std::string &funcName);
void updateFuncInfo(const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo);
void excludeArraysFromDistribution(const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> declaredArrays, std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::vector<ParallelRegion*> parallelRegions, std::map<std::string, std::vector<Messages>>& SPF_messages, std::map<std::tuple<int, std::string, std::string>, DIST::Array*>& createdArrays, int sharedMemoryParallelization = 0);
#if __SPF
void functionAnalyzer(SgFile *file, std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, const std::vector<LoopGraph*> &loops, std::vector<Messages> &messagesForFile, std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR);
int CheckFunctionsToInline(SgProject *proj, const std::map<std::string, int> &files, const char *fileName,
std::map<std::string, std::vector<FuncInfo*>> &funcByFile, const std::map<std::string, std::vector<LoopGraph*>> &loopGraph,
std::map<std::string, std::vector<Messages>> &allMessages, bool needToAddErrors,
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, const std::vector<ParallelRegion*> &regions);
void checkForRecursion(SgFile *file, std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, std::vector<Messages> &messagesForFile);
bool isPassFullArray(SgExpression *ex);
void doMacroExpand(SgFile *file, std::vector<Messages> &messages);
void propagateWritesToArrays(std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo);
void detectCopies(std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo);
void fillInterfaceBlock(std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
parF detectExpressionType(SgExpression* exp);
void findContainsFunctions(SgStatement *st, std::vector<SgStatement*> &found, const bool searchAll = false);
void correctNameIfContains(SgStatement* call, SgExpression* exCall, std::string& name, const std::vector<SgStatement*>& containsFunctions, const std::string& prefix);
int countPerfectLoopNest(SgStatement* st);
void setInlineAttributeToCalls(const std::map<std::string, FuncInfo*>& allFunctions, const std::map<std::string, std::set<std::pair<std::string, int>>>& inDataChains, const std::map<std::string, std::vector<SgStatement*>>& hiddenData);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,509 @@
#pragma once
#include <vector>
#include <string>
#include <map>
#include <set>
#include "../Utils/errors.h"
#include "../Utils/types.h"
#include "../Distribution/DvmhDirective.h"
#include "../Distribution/Distribution.h"
struct DistrVariant;
struct ParallelDirective;
struct ParallelRegion;
class Statement;
struct FuncInfo;
namespace Distribution
{
class Array;
}
namespace DIST = Distribution;
void getRealArrayRefs(DIST::Array* addTo, DIST::Array* curr, std::set<DIST::Array*>& realArrayRefs, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
void getAllArrayRefs(DIST::Array* addTo, DIST::Array* curr, std::set<DIST::Array*>& realArrayRefs, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
struct LoopGraph
{
private:
std::vector<std::pair<DIST::Array*, DistrVariant*>> redistributeRules;
LoopGraph* needToSwapWith;
//for local directive creating in MPI mode
DIST::GraphCSR<int, double, attrType> accessGraph;
DIST::GraphCSR<int, double, attrType> reducedAccessGraph;
DataDirective dataDirectives;
//
public:
LoopGraph()
{
lineNumAfterLoop = lineNum = altLineNum = -1;
perfectLoop = 0;
hasGoto = false;
hasPrints = false;
hasUnknownArrayDep = false;
hasUnknownScalarDep = false;
hasUnknownArrayAssigns = false;
hasNonRectangularBounds = false;
hasIndirectAccess = false;
withoutDistributedArrays = false;
hasWritesToNonDistribute = false;
hasUnknownDistributedMap = false;
hasDifferentAlignRules = false;
hasNonPureProcedures = false;
hasDvmIntervals = false;
hasStops = false;
directive = NULL;
oldDirective = NULL;
directiveForLoop = NULL;
region = NULL;
needToSwapWith = NULL;
countOfIters = 0;
countOfIterNested = 1;
loop = NULL;
parent = NULL;
userDvmDirective = NULL;
startVal = endVal = stepVal = 0;
calculatedCountOfIters = 0;
executionTimeInSec = -1.0;
inDvmhRegion = 0;
isFor = false;
inCanonicalFrom = false;
hasAccessToSubArray = false;
hasSubstringRefs = false;
}
~LoopGraph()
{
needToSwapWith = NULL;
if (directive != NULL)
delete directive;
if (directiveForLoop != NULL)
delete directiveForLoop;
for (int i = 0; i < children.size(); ++i)
delete children[i];
calls.clear();
readOpsArray.clear();
readOps.clear();
writeOps.clear();
hasConflicts.clear();
acrossOutAttribute.clear();
accessGraph.ClearGraphCSR();
reducedAccessGraph.ClearGraphCSR();
}
void setForSwap(LoopGraph* with) { needToSwapWith = with; }
LoopGraph* getForSwap() const { return needToSwapWith; }
void clearForSwap()
{
for (auto& ch : children)
ch->clearForSwap();
needToSwapWith = NULL;
}
bool hasLimitsToParallel() const
{
return hasUnknownArrayDep || hasUnknownScalarDep || hasGoto || hasPrints || (hasConflicts.size() != 0) || hasStops || hasNonPureProcedures ||
hasUnknownArrayAssigns || hasNonRectangularBounds || hasIndirectAccess || hasWritesToNonDistribute || hasDifferentAlignRules || hasDvmIntervals ||
!isFor || lastprivateScalars.size() || hasAccessToSubArray || hasSubstringRefs;
}
bool hasLimitsToSplit() const
{
return hasGoto || hasStops || !isFor || hasPrints;
}
bool hasLimitsToCombine() const
{
return hasGoto || hasStops || !isFor || hasPrints || linesOfCycle.size();
}
void addConflictMessages(std::vector<Messages> *messages)
{
const int line = altLineNum > 0 ? altLineNum : lineNum;
if (hasUnknownArrayDep)
messages->push_back(Messages(NOTE, line, R113, L"unknown array dependency prevents parallelization of this loop", 3006));
if (hasUnknownScalarDep)
messages->push_back(Messages(NOTE, line, R114, L"unknown scalar dependency prevents parallelization of this loop", 3006));
if (hasGoto)
messages->push_back(Messages(NOTE, line, R115, L"internal/external moves via GOTO or EXIT operations prevent parallelization of this loop", 3006));
if (hasPrints)
messages->push_back(Messages(NOTE, line, R116, L"IO operations prevent parallelization of this loop", 3006));
if (hasStops)
messages->push_back(Messages(NOTE, line, R117, L"stop operations prevent parallelization of this loop", 3006));
if (hasConflicts.size() != 0)
messages->push_back(Messages(NOTE, line, R118, L"conflict writes operations prevent parallelization of this loop", 3006));
if (hasUnknownArrayAssigns)
messages->push_back(Messages(NOTE, line, R119, L"unknown array reference for writes prevent parallelization of this loop", 3006));
if (hasNonRectangularBounds)
messages->push_back(Messages(NOTE, line, R144, L"non rectangular bounds prevent parallelization of this loop", 3006));
if (hasIndirectAccess)
messages->push_back(Messages(NOTE, line, R120, L"indirect access by distributed array prevents parallelization of this loop", 3006));
if (hasWritesToNonDistribute)
messages->push_back(Messages(NOTE, line, R121, L"writes to non distributed array prevents parallelization of this loop", 3006));
if (hasDifferentAlignRules)
messages->push_back(Messages(NOTE, line, R122, L"different aligns between writes to distributed array prevents parallelization of this loop", 3006));
if (hasNonPureProcedures)
messages->push_back(Messages(NOTE, line, R123, L"non pure procedures prevent parallelization of this loop", 3006));
if (hasDvmIntervals)
messages->push_back(Messages(NOTE, line, R145, L"DVM intervals prevent parallelization of this loop", 3006));
if (!isFor || !inCanonicalFrom)
messages->push_back(Messages(NOTE, line, R178, L"This type of loop is not supported by the system", 3006));
if (lastprivateScalars.size())
messages->push_back(Messages(NOTE, line, R199, L"lastprivate scalar dependency prevents parallelization of this loop", 3006));
}
void setNewRedistributeRules(const std::vector<std::pair<DIST::Array*, DistrVariant*>> &newRedistributeRules)
{
// set to top and for all childs
redistributeRules = newRedistributeRules;
for (int i = 0; i < children.size(); ++i)
children[i]->setNewRedistributeRules(newRedistributeRules);
}
DistrVariant* getRedistributeRule(const DIST::Array *arrayT) const
{
DistrVariant *retVal = NULL;
for (int i = 0; i < redistributeRules.size(); ++i)
{
if (redistributeRules[i].first == arrayT)
{
retVal = redistributeRules[i].second;
break;
}
}
return retVal;
}
bool hasRedistribute() const { return redistributeRules.size(); }
ParallelDirective* recalculateParallelDirective()
{
std::vector<ParallelDirective*> baseDirs(perfectLoop);
LoopGraph *next = this;
for (int z = 0; z < perfectLoop; ++z)
{
baseDirs[z] = next->directiveForLoop;
if (z != perfectLoop - 1)
next = next->children[0];
}
ParallelDirective *parDirective = baseDirs[0];
for (int z = 1; z < baseDirs.size() && baseDirs[z]; ++z)
{
ParallelDirective *old = parDirective;
parDirective = *parDirective + *baseDirs[z];
if (z != 1)
delete old;
}
oldDirective = directive;
directive = parDirective;
return directive;
}
void restoreDirective()
{
if (oldDirective)
{
delete directive;
directive = oldDirective;
}
for (int i = 0; i < children.size(); ++i)
children[i]->restoreDirective();
}
void setRegionToChilds()
{
for (auto &loop : children)
{
loop->region = region;
loop->setRegionToChilds();
}
}
void recalculatePerfect();
void setWithOutDistrFlagToFalse()
{
for (auto &loop : children)
{
loop->withoutDistributedArrays = false;
loop->setWithOutDistrFlagToFalse();
}
}
void propagateUserDvmDir()
{
for (auto &loop : children)
{
if (loop->userDvmDirective == NULL)
loop->userDvmDirective = userDvmDirective;
loop->propagateUserDvmDir();
}
}
void propagateDvmhRegion(const int flag)
{
for (auto& loop : children)
{
loop->inDvmhRegion = flag;
loop->propagateDvmhRegion(flag);
}
}
std::string genLoopArrayName(const std::string &funcName) const
{
return funcName + "_loop_" + std::to_string(lineNum);
}
std::set<DIST::Array*> getAllArraysInLoop()
{
std::set<DIST::Array*> retVal(readOpsArray);
for (auto &elem : writeOps)
retVal.insert(elem.first);
return retVal;
}
void removeNonDistrArrays()
{
std::set<DIST::Array*> newUsedArrays;
for (auto &elem : usedArrays)
if (elem->GetDistributeFlagVal() == DIST::DISTR)
newUsedArrays.insert(elem);
usedArrays = newUsedArrays;
std::set<DIST::Array*> newUsedArraysW;
for (auto &elem : usedArraysWrite)
if (elem->GetDistributeFlagVal() == DIST::DISTR)
newUsedArraysW.insert(elem);
usedArraysWrite = newUsedArraysW;
readOpsArray.clear();
readOps.clear();
writeOps.clear();
hasConflicts.clear();
for (auto &ch : children)
ch->removeNonDistrArrays();
}
void removeGraphData()
{
accessGraph.ClearGraphCSR();
reducedAccessGraph.ClearGraphCSR();
for (auto& ch : children)
ch->removeGraphData();
}
void clearUserDirectives();
bool isArrayTemplatesTheSame(DIST::Array*& sameTemplate, const uint64_t regId, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls)
{
if (sharedMemoryParallelization != 0)
return true;
std::set<DIST::Array*> usedForRegAccess;
for (auto& array : writeOps)
{
std::set<DIST::Array*> realArrayRefs;
getRealArrayRefs(array.first, array.first, realArrayRefs, arrayLinksByFuncCalls);
for (auto& realArr : realArrayRefs)
usedForRegAccess.insert(realArr);
}
//read operations can be REMOTE_ACCESS
/*for (auto& array : readOps)
{
std::set<DIST::Array*> realArrayRefs;
getRealArrayRefs(array.first, array.first, realArrayRefs, arrayLinksByFuncCalls);
for (auto& realArr : realArrayRefs)
usedForRegAccess.insert(realArr);
}*/
std::set<DIST::Array*> usedTemplates;
for (auto& array : usedArrays)
{
std::set<DIST::Array*> realArrayRefs;
getRealArrayRefs(array, array, realArrayRefs, arrayLinksByFuncCalls);
for (auto& realArr : realArrayRefs)
{
if (usedForRegAccess.find(realArr) == usedForRegAccess.end())
continue;
auto templ = realArr->GetTemplateArray(regId);
//TODO: what about NULL?
if (templ)
usedTemplates.insert(templ);
}
}
if (usedArrays.size())
{
if (usedTemplates.size() == 0 || usedTemplates.size() > 1)
return false;
else
sameTemplate = *usedTemplates.begin();
}
return true;
}
bool hasParallelLoopsInChList();
DIST::GraphCSR<int, double, attrType>& getGraphToModify() { return accessGraph; }
const DIST::GraphCSR<int, double, attrType>& getGraph() const { return accessGraph; }
DataDirective& getDataDirToModify() { return dataDirectives; }
const DataDirective& getDataDir() const { return dataDirectives; }
void reduceAccessGraph();
void createVirtualTemplateLinks(const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, std::map<std::string, std::vector<Messages>>& SPF_messages, bool isMpiProgram = false);
bool hasParalleDirectiveBefore();
void analyzeParallelDirs();
void* getRealStat(const char* file) const;
public:
int lineNum;
int altLineNum;
int lineNumAfterLoop;
std::string fileName;
int perfectLoop;
int countOfIters; // calculated total with nested loops
double countOfIterNested;
double executionTimeInSec;
int calculatedCountOfIters; // calculated for current loop
int startVal, endVal, stepVal;
std::tuple<Expression*, Expression*, Expression*> startEndStepVals;
std::string loopSymbol;
std::pair<Expression*, Expression*> startEndExpr;
bool hasGoto;
std::vector<int> linesOfInternalGoTo;
std::vector<int> linesOfExternalGoTo;
std::vector<int> linesOfCycle;
bool hasPrints;
std::set<int> linesOfIO;
bool hasStops;
std::set<int> linesOfStop;
bool hasUnknownScalarDep;
std::vector<int> linesOfScalarDep;
bool hasUnknownArrayDep;
bool hasUnknownArrayAssigns;
bool hasNonRectangularBounds;
bool hasIndirectAccess;
bool hasWritesToNonDistribute;
bool withoutDistributedArrays;
bool hasUnknownDistributedMap;
bool hasDifferentAlignRules;
bool hasNonPureProcedures;
bool hasDvmIntervals;
// make sense only for NODIST regime
bool hasAccessToSubArray;
bool hasSubstringRefs;
bool isFor;
bool inCanonicalFrom;
std::vector<LoopGraph*> children;
std::vector<LoopGraph*> funcChildren;
LoopGraph *parent;
std::vector<LoopGraph*> funcParents;
// PAIR<FUNC_NAME, LINE>
std::vector<std::pair<std::string, int>> calls;
std::set<std::string> lastprivateScalars;
std::set<std::string> privateScalars;
std::map<DIST::Array*, std::vector<ArrayOp>> readOpsForLoop;
std::map<DIST::Array*, std::vector<ArrayOp>> writeOpsForLoop;
// agregated read and write operations by arrays
std::set<DIST::Array*> readOpsArray;
std::map<DIST::Array*, std::pair<std::vector<ArrayOp>, std::vector<bool>>> readOps;
std::map<DIST::Array*, std::vector<ArrayOp>> writeOps;
std::map<DIST::Array*, std::vector<ArrayOp>> remoteRegularReads;
std::map<DIST::Array*, bool> hasConflicts;
std::set<DIST::Array*> acrossOutAttribute;
ParallelDirective *directive; // united directive for nested loops
ParallelDirective *oldDirective; // save old directive for reverse
ParallelDirective *directiveForLoop; // part of directive for loop
Statement *userDvmDirective; // user's DVM PARALLEL directive
ParallelRegion *region;
Statement *loop;
std::set<DIST::Array*> usedArrays;// without NON DIST
std::set<DIST::Array*> usedArraysAll;
std::set<DIST::Array*> usedArraysWrite; // without NON DIST
std::set<DIST::Array*> usedArraysWriteAll;
int inDvmhRegion; // 0 -unknown, -1 - no, 1 - yes
};
void processLoopInformationForFunction(std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>>& loopInfo);
void addToDistributionGraph(const std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>>& loopInfo, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
void selectFreeLoopsForParallelization(const std::vector<LoopGraph*>& loops, const std::string& funcName, bool isDistribute, const std::vector<ParallelRegion*>& regions, std::vector<Messages>& messagesForFile);
void convertToString(const LoopGraph* currLoop, std::string& result);
int printLoopGraph(const char* fileName, const std::map<std::string, std::vector<LoopGraph*>>& loopGraph, bool withRegs = false);
void checkCountOfIter(std::map<std::string, std::vector<LoopGraph*>>& loopGraph, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, std::map<std::string, std::vector<Messages>>& SPF_messages);
void createMapLoopGraph(const std::vector<LoopGraph*>& loops, std::map<int, LoopGraph*>& mapGraph);
void updateLoopIoAndStopsByFuncCalls(std::map<std::string, std::vector<LoopGraph*>>& loopGraph, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
void checkArraysMapping(const std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::map<std::string, std::vector<Messages>>& SPF_messages, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
void filterArrayInCSRGraph(std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::map<std::string, std::vector<FuncInfo*>>& allFuncs, ParallelRegion* reg, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, std::map<std::string, std::vector<Messages>>& messages);
void swapLoopsForParallel(std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::map<std::string, std::vector<Messages>>& SPF_messages, const int rev);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
#pragma once
#include <vector>
#include <map>
#include "graph_loops.h"
#include "../Distribution/DvmhDirective.h"
struct SpfInterval;
void loopGraphAnalyzer(SgFile *file, std::vector<LoopGraph*> &loopGraph, const std::vector<SpfInterval*> &statisticTimes, std::vector<Messages> &messages, int sharedMemoryParallelization);
void findAllRefsToLables(SgStatement *st, std::map<int, std::vector<int>> &labelsRef, bool includeWrite = true);
std::map<LoopGraph*, ParallelDirective*> findAllDirectives(SgFile *file, const std::vector<LoopGraph*> &loops, const uint64_t regId);
std::vector<std::tuple<DIST::Array*, std::vector<long>, std::pair<std::string, int>>> findAllSingleRemotes(SgFile *file, const uint64_t regId, std::vector<ParallelRegion*> &regions);
std::map<DIST::Array*, std::vector<long>> fillRemoteInParallel(Statement *st);
bool hasThisIds(SgStatement *loop, std::set<int> &lines, const std::set<int> &IDs, const std::set<SgStatement*>* activeOps = NULL);
bool checkRegionEntries(SgStatement *begin, SgStatement *end, const std::map<std::string, FuncInfo*> &funcMap, const std::vector<ParallelRegion*> &parallelRegions, std::map<std::string, std::vector<Messages>> &SPF_messages);
bool recSymbolFind(SgExpression *ex, const std::string &symb, const int var);
void completeFillOfArrayUsageBetweenProc(const std::map<std::string, std::vector<LoopGraph*>>& loopGraph, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
bool detectMpiCalls(SgProject* proj, std::map<std::string, std::vector<Messages>>& SPF_messages);
int calculateLoopIters(SgExpression* start, SgExpression* end, SgExpression* step, std::tuple<int, int, int>& result);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
#pragma once
#include <set>
#include <vector>
#include <map>
#include <string>
void callInliner(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo,
std::vector<std::tuple<std::string, std::string, int>>& inDataProc,
std::map<std::string, std::set<std::pair<std::string, int>>>& inDataChains,
const std::set<std::string>& inDataChainsStart,
std::map<std::string, std::vector<Messages>>& SPF_messages,
const std::map<std::string, CommonBlock*>& commonBlocks);

View File

@@ -0,0 +1,241 @@
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <assert.h>
#include <set>
#include "dvm.h"
#include "../Utils/SgUtils.h"
#include "../Utils/errors.h"
using std::set;
using std::pair;
using std::map;
using std::vector;
using std::string;
void preprocess_allocates(SgFile *file)
{
const string currfile = file->filename();
int funcNum = file->numberOfFunctions();
set<SgStatement*> allStats;
for (auto st = file->firstStatement(); st != NULL; st = st->lexNext())
allStats.insert(st);
for (int i = 0; i < funcNum; ++i)
{
SgStatement *st = file->functions(i);
SgStatement *lastNode = st->lastNodeOfStmt();
while (st != lastNode)
{
if (st == NULL)
{
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
break;
}
if (st->variant() == CONTAINS_STMT)
break;
// save SgStatement PROC call to declaration attribute
if (st->variant() == ALLOCATE_STMT || st->variant() == DEALLOCATE_STMT)
{
SgExpression *list = st->expr(0);
set<SgStatement*> decls;
while (list)
{
if (list->lhs()->variant() == ARRAY_REF)
decls.insert(declaratedInStmt(OriginalSymbol(isSgArrayRefExp(list->lhs())->symbol())));
else if (list->lhs()->variant() == RECORD_REF)
{
SgExpression* field = list->lhs()->lhs();
if (field->variant() == ARRAY_REF)
decls.insert(declaratedInStmt(OriginalSymbol(field->symbol())));
else if (field->variant() == VAR_REF)
decls.insert(declaratedInStmt(OriginalSymbol(field->symbol())));
else
printf(""); // TODO
}
list = list->rhs();
}
set<SgStatement*> altDecls;
for (auto& decl : decls)
{
if (decl->fileName() != currfile)
{
const string fIncl = decl->fileName();
for (auto& stat : allStats)
if (stat->lineNumber() == decl->lineNumber() && stat->fileName() == fIncl && decl != stat)
altDecls.insert(stat);
}
}
for (auto& alt : altDecls)
decls.insert(alt);
char buf[256];
for (auto& decl : decls)
{
decl->addAttribute(st->variant(), st, sizeof(SgStatement*));
sprintf(buf, " attribute (%d %s) is added to declaration on line %d of %s file\n",
st->lineNumber(), st->fileName(), decl->lineNumber(), decl->fileName());
addToGlobalBufferAndPrint(buf);
}
if (decls.size() == 0)
{
sprintf(buf, "ERROR at line %d %s: Can not find declarations for allocation on line %d\n", __LINE__, convertFileName(__FILE__).c_str(), st->lineNumber());
addToGlobalBufferAndPrint(buf);
throw(-1);
}
}
st = st->lexNext();
}
}
}
//TODO: extend ALLOC/DEALLOC moving
//TODO: add support of different files
// only one level of call is supported
void moveAllocatesInterproc(const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
{
for (auto &array : arrayLinksByFuncCalls)
{
if (array.first->GetLocation().first == DIST::l_PARAMETER)
{
//check one level of calls
bool ok = true;
for (auto &elem : array.second)
if (elem->GetLocation().first == DIST::l_PARAMETER)
ok = false;
//move to all real arrays
if (ok)
{
auto allPlaces = array.first->GetDeclInfo();
for (auto &place : allPlaces)
{
if (SgFile::switchToFile(place.first) != -1)
{
SgStatement *decl = SgStatement::getStatementByFileAndLine(place.first, place.second);
checkNull(decl, convertFileName(__FILE__).c_str(), __LINE__);
map<SgStatement*, set<SgStatement*>> needToAdd;
for (auto &data : getAttributes<SgStatement*, SgStatement*>(decl, set<int>{ ALLOCATE_STMT }))
{
for (auto &realArray : array.second)
{
auto allPlacesR = realArray->GetDeclInfo();
for (auto &placeR : allPlacesR)
{
//the same file
if (placeR.first == place.first)
{
SgStatement* declR = SgStatement::getStatementByFileAndLine(placeR.first, placeR.second);
checkNull(declR, convertFileName(__FILE__).c_str(), __LINE__);
needToAdd[declR].insert(data);
}
}
}
}
for (auto& toAdd : needToAdd)
{
for (auto& list : toAdd.second)
{
char buf[256];
toAdd.first->addAttribute(list->variant(), list, sizeof(SgStatement*));
sprintf(buf, " [INTERPROC] attribute is added to declaration on line %d\n", toAdd.first->lineNumber());
addToGlobalBufferAndPrint(buf);
}
}
}
}
}
}
}
map<string, map<int, set<SgStatement*>>> attrsForModules; // mod -> [ line -> decls]
//get module declarations
for (int z = 0; z < CurrentProject->numberOfFiles(); ++z)
{
SgFile* file = &(CurrentProject->file(z));
vector<SgStatement*> modules;
findModulesInFile(file, modules);
for (auto& mod : modules)
{
SgStatement* st = mod;
SgStatement* end = mod->lastNodeOfStmt();
string modName = mod->symbol()->identifier();
while (st != end)
{
if (st->variant() == CONTAINS_STMT)
break;
for (auto& data : getAttributes<SgStatement*, SgStatement*>(st, set<int>{ ALLOCATE_STMT, DEALLOCATE_STMT }))
attrsForModules[modName][st->lineNumber()].insert(data);
st = st->lexNext();
}
}
}
//synchronize module declarations
for (int z = 0; z < CurrentProject->numberOfFiles(); ++z)
{
SgFile* file = &(CurrentProject->file(z));
vector<SgStatement*> modules;
findModulesInFile(file, modules);
for (auto& mod : modules)
{
SgStatement* st = mod;
SgStatement* end = mod->lastNodeOfStmt();
string modName = mod->symbol()->identifier();
if (attrsForModules.find(modName) == attrsForModules.end())
continue;
auto& info = attrsForModules[modName];
while (st != end)
{
if (st->variant() == CONTAINS_STMT)
break;
if (info.find(st->lineNumber()) != info.end())
{
const set<SgStatement*>& decls = info[st->lineNumber()];
auto attrs = getAttributes<SgStatement*, SgStatement*>(st, set<int>{ ALLOCATE_STMT, DEALLOCATE_STMT });
const set<SgStatement*> inAttr(attrs.begin(), attrs.end());
for (auto& data : decls)
{
if (inAttr.find(data) == inAttr.end())
{
char buf[256];
st->addAttribute(data->variant(), data, sizeof(SgStatement*));
sprintf(buf, " [MODULE SYNC] attribute (%d %s) is added to declaration on line %d of %s file\n",
data->lineNumber(), data->fileName(), st->lineNumber(), st->fileName());
addToGlobalBufferAndPrint(buf);
}
}
}
st = st->lexNext();
}
}
}
}

View File

@@ -0,0 +1,448 @@
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <string>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <assert.h>
#include <chrono>
#include "dvm.h"
#include "loop_analyzer.h"
#include "../Utils/utils.h"
#include "../Utils/SgUtils.h"
#include "../ParallelizationRegions/ParRegions_func.h"
#include "../SageAnalysisTool/depGraph.h"
#include "../SageAnalysisTool/OmegaForSage/include/lang-interf.h"
using std::vector;
using std::pair;
using std::tuple;
using std::map;
using std::set;
using std::make_pair;
using std::make_tuple;
using std::get;
using std::string;
using std::wstring;
using std::chrono::high_resolution_clock;
using std::chrono::duration_cast;
using std::chrono::milliseconds;
extern map<LoopGraph*, depGraph*> depInfoForLoopGraph;
extern void initializeDepAnalysisForFunction(SgFile *file, SgStatement *func, const map<string, FuncInfo*> &allFuncs, vector<Messages> &messagesForFile);
extern int staticPrivateAnalysis;
extern bool fullDepGraph;
static const set<string> *currentNonDistrArrays = NULL;
static map<SgSymbol*, string> varInOut;
static map<SgExpression*, string> *currentCollection = NULL;
bool isRemovableDependence(const depNode *currNode, const set<string> &privVars)
{
bool result = true;
bool varIn = false, varOut = false;
switch (currNode->typedep)
{
case WRONGDEP:
result = false;
break;
case ARRAYDEP:
if (currentNonDistrArrays && currentNonDistrArrays->size() > 0)
{
SgSymbol *vIn = OriginalSymbol(currNode->varin->symbol());
SgSymbol *vOut = OriginalSymbol(currNode->varout->symbol());
auto found = varInOut.find(vIn);
if (found == varInOut.end())
found = varInOut.insert(found, make_pair(vIn, vIn->identifier()));
varIn = currentNonDistrArrays->find(found->second) != currentNonDistrArrays->end();
found = varInOut.find(vOut);
if (found == varInOut.end())
found = varInOut.insert(found, make_pair(vOut, vOut->identifier()));
varOut = currentNonDistrArrays->find(found->second) != currentNonDistrArrays->end();
}
//dont check if textual identically
if ((!isEqExpressions(currNode->varin, currNode->varout, *currentCollection) || varIn || varOut) && (currNode->varin != currNode->varout))
{
// TODO: process all loop, not only top loop
if (currNode->knowndist[1] == 0 || currNode->distance[1] != 0)
{
if (currNode->knowndist[1] == 0)
result = false;
}
else if (varIn || varOut) // found dependencies between non ditributed arrays
{
result = false;
}
}
break;
case PRIVATEDEP:
case REDUCTIONDEP:
break;
case SCALARDEP:
if (privVars.find(currNode->varin->symbol()->identifier()) == privVars.end())
result = false;
break;
default:
result = false;
break;
}
return result;
}
static SgStatement* getCurrentFunc(SgStatement *st)
{
while (st && st->variant() != PROG_HEDR && st->variant() != PROC_HEDR && st->variant() != FUNC_HEDR)
st = st->controlParent();
checkNull(st, convertFileName(__FILE__).c_str(), __LINE__);
return st;
}
depGraph *getDependenciesGraph(const LoopGraph *currLoop, SgFile *file, const set<string> *privVars)
{
SgForStmt *currLoopRef = (SgForStmt*)currLoop->loop->GetOriginal();
auto t = high_resolution_clock::now();
map<SgExpression*, string> tmpCollection;
currentCollection = &tmpCollection;
set<string> tmpPriv;
depGraph *depg = new depGraph(file, getCurrentFunc(currLoopRef), currLoopRef, privVars ? *privVars : tmpPriv);
float elapsed = duration_cast<milliseconds>(high_resolution_clock::now() - t).count() / 1000.;
if (elapsed > 1.0f)
printf("SAPFOR: time of graph bulding for loop %d = %f sec\n", currLoop->lineNum, elapsed);
currentCollection = NULL;
return depg;
}
//TODO: remove?
static int isOnlyDef(SgStatement *loopSt, const map<SgStatement*, vector<DefUseList>> &defUseByPlace, const string &symb)
{
SgStatement *last = loopSt->lastNodeOfStmt();
bool wasFoundSome = false;
int count = 0;
for (auto st = loopSt; st != last; st = st->lexNext())
{
auto it = defUseByPlace.find(st);
if (it != defUseByPlace.end())
{
for (auto &elem : it->second)
{
if (elem.getVar() == symb)
{
wasFoundSome = true;
if (elem.isUse())
return -1;
if (elem.isDef())
count++;
}
}
}
}
if (!wasFoundSome)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return count;
}
static set<string> fillNestedReduction(LoopGraph* currLoop)
{
set<string> redVars;
tryToFindPrivateInAttributes(currLoop->loop, redVars, true, true);
int lastPerfect = currLoop->perfectLoop;
currLoop = currLoop->parent;
while (currLoop && currLoop->perfectLoop == lastPerfect + 1)
{
tryToFindPrivateInAttributes(currLoop->loop, redVars, true, true);
lastPerfect = currLoop->perfectLoop;
currLoop = currLoop->parent;
}
return redVars;
}
static SgExpression *startS = NULL, *endS = NULL;
static SgExpression *startS_save = NULL, *endS_save = NULL;
// try to find dependencies: reductions and privates for scalar
// and regular and other for arrrays
//TODO: add optimization - dont call omega test for arrays many times
void tryToFindDependencies(LoopGraph *currLoop, const map<int, pair<SgForStmt*, pair<set<string>, set<string>>>> &allLoops,
set<SgStatement*> &funcWasInit, SgFile *file, vector<ParallelRegion*> regions,
vector<Messages> *currMessages,
map<SgExpression*, string> &collection,
const map<string, FuncInfo*> &allFuncs, const map<SgStatement*, vector<DefUseList>> &defUseByPlace)
{
auto it = allLoops.find(currLoop->lineNum);
if (it == allLoops.end())
return;
map<int, SgForStmt*> localAllLoopMap;
for (auto &elem : allLoops)
localAllLoopMap.insert(make_pair(elem.first, elem.second.first));
ParallelRegion *currReg = getRegionByLine(regions, it->second.first->fileName(), currLoop->lineNum);
if (currReg && currLoop->hasLimitsToParallel() == false || fullDepGraph)
{
SgForStmt *currLoopRef = it->second.first;
set<string> redVars = fillNestedReduction(currLoop);
bool onlyOneStep = false;
// if identical
/*string startL = string(currLoopRef->start()->unparse());
string endL = string(currLoopRef->end()->unparse());
if (startL == endL)
onlyOneStep = true;*/
// XXX: turn off this "optimization"
//make unknown iters count for better analysis
bool interChanged = false;
if (currLoop->countOfIters == 1)
{
interChanged = true;
if (!startS)
startS = new SgExpression(VAR_REF, new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "_tmp1_")));
if (!endS)
endS = new SgExpression(VAR_REF, new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "_tmp2_")));
startS_save = currLoopRef->start();
endS_save = currLoopRef->end();
currLoopRef->setStart(*startS);
currLoopRef->setEnd(*endS);
}
const set<string> &privVars = it->second.second.first;
const set<string> &nonDistrArrays = it->second.second.second;
SgStatement *func = getFuncStat(currLoopRef);
if (funcWasInit.find(func) == funcWasInit.end())
{
funcWasInit.insert(func);
initializeDepAnalysisForFunction(file, func, allFuncs, *currMessages);
}
currentNonDistrArrays = &nonDistrArrays;
currentCollection = &collection;
depGraph *depg = getDependenciesGraph(currLoop, file, &privVars);
if (interChanged)
{
currLoopRef->setStart(*startS_save);
currLoopRef->setEnd(*endS_save);
}
currentNonDistrArrays = NULL;
currentCollection = NULL;
/*auto t = high_resolution_clock::now();
depGraph *depg = new depGraph(file, getCurrentFunc(currLoopRef), currLoopRef, privVars);
float elapsed = duration_cast<milliseconds>(high_resolution_clock::now() - t).count() / 1000.;
if (elapsed > 1.0f)
printf("SAPFOR: time of graph bulding for loop %d = %f sec\n", currLoop->lineNum, elapsed);*/
if (depg)
{
const std::vector<depNode*> &nodes = depg->getNodes();
//vector<const depNode*> privatesToAdd;
vector<const depNode*> reductionsToAdd;
vector<const depNode*> unknownScalarDep;
bool findUnknownDepLen = false;
map<SgSymbol*, tuple<int, int, int>> acrossToAdd;
bool varIn = false, varOut = false;
bool isEqual = false;
for (int k = 0; k < nodes.size(); ++k)
{
const depNode *currNode = nodes[k];
switch (currNode->typedep)
{
case WRONGDEP:
break;
case ARRAYDEP:
if (nonDistrArrays.size() > 0)
{
SgSymbol *vIn = OriginalSymbol(currNode->varin->symbol());
SgSymbol *vOut = OriginalSymbol(currNode->varout->symbol());
auto found = varInOut.find(vIn);
if (found == varInOut.end())
found = varInOut.insert(found, make_pair(vIn, vIn->identifier()));
varIn = nonDistrArrays.find(found->second) != nonDistrArrays.end();
found = varInOut.find(vOut);
if (found == varInOut.end())
found = varInOut.insert(found, make_pair(vOut, vOut->identifier()));
varOut = nonDistrArrays.find(found->second) != nonDistrArrays.end();
}
isEqual = isEqExpressions(currNode->varin, currNode->varout, collection);
//dont check if textual identically
if ((!isEqual || varIn || varOut) && (currNode->varin != currNode->varout))
{
// TODO: process all loop, not only top loop
if (currNode->knowndist[1] == 0 || currNode->distance[1] != 0)
{
if (currNode->knowndist[1] == 0)
{
if (!findUnknownDepLen)
{
auto message = currNode->createDepMessagebetweenArrays();
wstring depMessageEng = to_wstring(message.first), depMessageRus = to_wstring(message.second);
depMessageEng += L" with unknown distance in loop on line " + std::to_wstring(currLoopRef->lineNumber()) + L" prevents parallelization";
depMessageRus += L"#" + std::to_wstring(currLoopRef->lineNumber());
currMessages->push_back(Messages(NOTE, currNode->stmtin->lineNumber(), L"R124:" + depMessageRus, depMessageEng, 3006));
// __spf_print only first unknown dep length
findUnknownDepLen = true;
if (!onlyOneStep)
currLoop->hasUnknownArrayDep = true;
}
}
else if (!findUnknownDepLen) //currNode->distance[1] != 0
{
const ddnature nature = (ddnature)currNode->kinddep;
int position = -1;
if (nature == ddflow)
position = 0;
else if (nature == ddanti)
position = 1;
if (position != -1)
{
SgSymbol *arrayS = OriginalSymbol(currNode->varin->symbol());
SgArrayRefExp *arrayRef = (SgArrayRefExp*)(currNode->varin);
bool existSubs = false;
auto it = acrossToAdd.find(arrayS);
if (it == acrossToAdd.end())
{
int subsPos = -1;
SgSymbol *doName = currLoopRef->symbol();
for (int z = 0; z < arrayRef->numberOfSubscripts() && !existSubs; ++z)
{
existSubs = checkExistence(arrayRef->subscript(z), doName->identifier());
if (existSubs)
subsPos = z;
}
if (existSubs)
it = acrossToAdd.insert(it, make_pair(arrayS, make_tuple(0, 0, subsPos)));
}
else
existSubs = true;
if (existSubs)
{
if (position == 0)
get<0>(it->second) = std::max(get<0>(it->second), abs((int)currNode->distance[1]));
else
get<1>(it->second) = std::max(get<1>(it->second), abs((int)currNode->distance[1]));
}
}
}
}
else if (!isEqual && (varIn || varOut)) // found dependencies between non ditributed arrays
{
if (currNode->knowndist[1] == 0 || currNode->distance[1] != 0)
{
if (!findUnknownDepLen)
{
auto message = currNode->createDepMessagebetweenArrays();
wstring depMessageEng = to_wstring(message.first), depMessageRus = to_wstring(message.second);
depMessageEng += L" prevents parallelization";
currMessages->push_back(Messages(NOTE, currNode->stmtin->lineNumber(), L"R124:" + depMessageRus, depMessageEng, 3006));
// __spf_print only first unknown dep length
findUnknownDepLen = true;
if (!onlyOneStep)
currLoop->hasUnknownArrayDep = true;
}
}
}
}
//currNode->displayDep();
break;
case PRIVATEDEP: //privates detected by PRIVATE_ANALYSIS_IR
/*if (privVars.find(currNode->varin->symbol()->identifier()) == privVars.end())
privatesToAdd.push_back(currNode);
//unknownScalarDep.push_back(currNode); */
break;
case REDUCTIONDEP:
if (currLoop->privateScalars.find(currNode->varin->symbol()->identifier()) == currLoop->privateScalars.end() &&
redVars.find(currNode->varin->symbol()->identifier()) == redVars.end())
reductionsToAdd.push_back(currNode);
break;
case SCALARDEP:
if (currLoop->privateScalars.find(currNode->varin->symbol()->identifier()) == currLoop->privateScalars.end() &&
redVars.find(currNode->varin->symbol()->identifier()) == redVars.end())
unknownScalarDep.push_back(currNode);
break;
default:
break;
}
}
if (!onlyOneStep)
{
//NOTE: do it via PRIVATE_ANALYSIS_IR
//addPrivatesToLoops(currLoop, privatesToAdd, localAllLoopMap, *currMessages);
addReductionsToLoops(currLoop, reductionsToAdd, localAllLoopMap, *currMessages);
if (!findUnknownDepLen && !currLoop->hasLimitsToParallel())
addAcrossToLoops(currLoop, acrossToAdd, localAllLoopMap, *currMessages);
currLoop->hasUnknownScalarDep = (unknownScalarDep.size() != 0);
for (int k = 0; k < unknownScalarDep.size(); ++k)
{
__spf_print(1, " unknown scalar dependencies by '%s' on line %d (try to specify its type)\n",
unknownScalarDep[k]->varin->symbol()->identifier(), unknownScalarDep[k]->stmtin->lineNumber());
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"unknown scalar dependencies by '%s' (try to specify its type)", to_wstring(unknownScalarDep[k]->varin->symbol()->identifier()).c_str());
__spf_printToLongBuf(messageR, R112, to_wstring(unknownScalarDep[k]->varin->symbol()->identifier()).c_str());
currMessages->push_back(Messages(WARR, unknownScalarDep[k]->stmtin->lineNumber(), messageR, messageE, 3005));
currLoop->linesOfScalarDep.push_back(unknownScalarDep[k]->stmtin->lineNumber());
}
}
depInfoForLoopGraph[currLoop] = depg;
if (currLoop->hasLimitsToParallel())
currLoop->addConflictMessages(currMessages);
}
}
else if (currReg && currLoop->hasLimitsToParallel())
{
// loop has limits
currLoop->addConflictMessages(currMessages);
}
for (int k = 0; k < currLoop->children.size(); ++k)
tryToFindDependencies(currLoop->children[k], allLoops, funcWasInit, file, regions, currMessages, collection, allFuncs, defUseByPlace);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
#pragma once
#include <map>
#include <string>
#include <tuple>
#include <vector>
#include <set>
#include "../GraphLoop/graph_loops.h"
#include "../GraphCall/graph_calls.h"
#include "../ParallelizationRegions/ParRegions.h"
#include "../SageAnalysisTool/depInterfaceExt.h"
#include "../Utils/AstWrapper.h"
#include "../Utils/SgUtils.h"
#include "dvm.h"
typedef std::pair<std::pair<int, int>, std::pair<int, int>> attrType;
namespace DIST = Distribution;
enum REGIME { DATA_DISTR, COMP_DISTR, REMOTE_ACC, ARRAY_ACC_CORNER, SHARED_MEMORY_PAR, UNDEF };
// loop_analyzer.cpp
bool checkExistence(SgExpression *exp, const std::string& doName);
void loopAnalyzer(SgFile *file,
std::vector<ParallelRegion*> &regions,
std::map<std::tuple<int, std::string, std::string>, DIST::Array*> &createdArrays,
std::vector<Messages> &messagesForFile,
REGIME regime,
const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo,
const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
const std::map<SgStatement*, std::set<std::tuple<int, std::string, std::string>>> &declaratedArraysSt,
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls,
const std::map<SgStatement*, std::vector<DefUseList>> &defUseByPlace,
bool skipDeps, std::vector<LoopGraph*> *loopGraph = NULL);
void fillFromModule(SgSymbol* s, const std::map<std::string, std::set<std::string>>& privatesByModule, std::set<std::string>& privates);
std::vector<std::pair<Expression*, Expression*>> getArraySizes(std::vector<std::pair<int, int>>& sizes, SgSymbol* symb, SgStatement* decl,
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
void arrayAccessAnalyzer(SgFile *file, std::vector<Messages> &messagesForFile,
const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
REGIME regime);
void processLoopInformationForFunction(std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>> &loopInfo);
void addToDistributionGraph(const std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>> &loopInfo, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls);
void printBlanks(const int sizeOfBlank, const int countOfBlanks);
bool isIntrinsic(const char *funName);
std::tuple<int, std::string, std::string> getUniqName(const std::map<std::string, SgStatement*> &commonBlocks, SgStatement *decl, SgSymbol *symb);
std::string getShortName(const std::tuple<int, std::string, std::string> &uniqKey);
void insertSpfAnalysisBeforeParalleLoops(const std::vector<LoopGraph*> &loops);
void recalculateArraySizes(std::set<DIST::Array*> &arraysDone, const std::set<DIST::Array*> &allArrays, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
int getSizeOfType(SgType* t);
// dep_analyzer.cpp
void tryToFindDependencies(LoopGraph *currLoop, const std::map<int, std::pair<SgForStmt*, std::pair<std::set<std::string>, std::set<std::string>>>> &allLoops,
std::set<SgStatement*> &funcWasInit, SgFile *file, std::vector<ParallelRegion*> regions, std::vector<Messages> *currMessages,
std::map<SgExpression*, std::string> &collection, const std::map<std::string, FuncInfo*> &allFuncs,
const std::map<SgStatement*, std::vector<DefUseList>> &defUseByPlace);
depGraph *getDependenciesGraph(const LoopGraph *currLoop, SgFile *file, const std::set<std::string> *privVars = NULL);
// allocations_prepoc.cpp
void preprocess_allocates(SgFile *file);
void moveAllocatesInterproc(const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
// spf_directive_preproc.cpp
bool preprocess_spf_dirs(SgFile *file, const std::map<std::string, CommonBlock*> &commonBlocks, std::vector<Messages> &messagesForFile, const std::set<std::string>& allFileNames, std::map<std::pair<std::string, int>, std::set<SgStatement*>>& usersDirectives);
bool check_par_reg_dirs(SgFile *file, std::vector<Messages> &messagesForFile);
void revertion_spf_dirs(SgFile *file,
std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> declaredArrays,
std::map<SgStatement*, std::set<std::tuple<int, std::string, std::string>>> declaratedArraysSt);
void addAcrossToLoops(LoopGraph *topLoop, const std::map<SgSymbol*, std::tuple<int, int, int>> &acrossToAdd,
const std::map<int, SgForStmt*> &allLoops,
std::vector<Messages> &currMessages);
void addPrivatesToLoops(LoopGraph *currLoop, const std::vector<const depNode*> &privatesToAdd,
const std::map<int, SgForStmt*> &allLoops,
std::vector<Messages> &currMessages);
void addReductionsToLoops(LoopGraph *currLoop, const std::vector<const depNode*> &reductionsToAdd,
const std::map<int, SgForStmt*> &allLoops,
std::vector<Messages> &currMessages);
void fillVars(SgExpression *exp, const std::set<int> &types, std::set<SgSymbol*> &identifierList, std::vector<SgExpression*> &funcCalls);
// TODO: from remote_access.cpp, may be need to move
bool isNeedToConvertIfCondition(SgExpression* ex);
void addRemotesToDir(const std::pair<SgForStmt*, LoopGraph*> *under_dvm_dir, const std::map<std::string, ArrayRefExp*> &uniqRemotes);
void fillRemoteFromDir(SgExpression* ex, std::vector<SgExpression*>& remotes);
template<int NUM> bool createRemoteDir(SgStatement *st, const std::map<std::string, FuncInfo*>& funcMap, const std::map<int, LoopGraph*> &sortedLoopGraph, const DIST::Arrays<int> &allArrays,
const DataDirective &data, const std::vector<int> &currVar, const uint64_t regionId, std::vector<Messages> &currMessages,
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls);
void groupActualAndRemote(SgFile* file, bool revert = false);
std::vector<SgStatement*> filterUserSpf(const std::vector<SgStatement*>& toFilter, bool with_omp = true);
// ArrayAnalysis.cpp
int getAllDeclaredArrays(SgFile *file, std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
std::map<SgStatement*, std::set<std::tuple<int, std::string, std::string>>> &declaratedArraysSt, std::map<std::string, std::vector<Messages>> &currMessages,
const std::vector<ParallelRegion*> &regions, const std::map<std::string, int>& distrStateFromGUI);

View File

@@ -0,0 +1,896 @@
#include "../Utils/leak_detector.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
#include "dvm.h"
#include "ParRegions.h"
#include "../Utils/utils.h"
#include "../Utils/SgUtils.h"
#include "../GraphCall/graph_calls_func.h"
#include "../GraphLoop/graph_loops.h"
#include "../Distribution/Distribution.h"
#include "../ExpressionTransform/expr_transform.h"
using std::vector;
using std::string;
using std::pair;
using std::make_pair;
using std::map;
using std::set;
using std::wstring;
extern void createMapLoopGraph(map<int, LoopGraph*> &sortedLoopGraph, const vector<LoopGraph*> *loopGraph);
static map<string, int> regionIdByName;
static map<string, ParallelRegion*> regionByName;
static int regionIdConuter = 1;
void clearRegionStaticData()
{
regionIdByName.clear();
regionByName.clear();
regionIdConuter = 1;
}
static inline void extendRegionInfo(SgStatement *st, map<string, pair<Statement*, Statement*>> &startEnd, map<string, pair<int, int>> &lines_, bool addEndSt = false)
{
auto it_st_en = startEnd.find(st->fileName());
if (it_st_en == startEnd.end())
{
startEnd.insert(it_st_en, make_pair(st->fileName(), make_pair<Statement*, Statement*>(new Statement(st), NULL)));
lines_[st->fileName()] = make_pair(st->lineNumber(), 0);
}
else
{
if (addEndSt)
{
Statement *toAdd = new Statement(st);
it_st_en->second.second = toAdd;
}
lines_[st->fileName()].second = st->lineNumber();
}
}
static void findFuncCalls(SgExpression *ex, set<string> &calls, const string &prefix, const map<string, FuncInfo*>& mapFuncs)
{
if (ex == NULL)
return;
if (ex->variant() == FUNC_CALL)
{
string fullName = ex->symbol()->identifier();
//check contains
if (mapFuncs.find(prefix + fullName) != mapFuncs.end())
fullName = prefix + fullName;
calls.insert(fullName);
}
findFuncCalls(ex->lhs(), calls, prefix, mapFuncs);
findFuncCalls(ex->rhs(), calls, prefix, mapFuncs);
}
static inline SgStatement* getParentStat(SgStatement *st)
{
if (!st)
return NULL;
SgStatement *iterator = st;
while (iterator->variant() != PROG_HEDR && iterator->variant() != PROC_HEDR && iterator->variant() != FUNC_HEDR)
iterator = iterator->controlParent();
while (iterator->controlParent()->variant() == PROG_HEDR || iterator->controlParent()->variant() == PROC_HEDR || iterator->controlParent()->variant() == FUNC_HEDR)
iterator = iterator->controlParent();
return iterator;
}
static void updateRegionInfo(SgStatement *st, map<string, pair<Statement*, Statement*>> &startEnd, map<string, pair<int, int>> &lines_,
set<string> &funcCallFromReg, const map<string, FuncInfo*> &mapFuncs)
{
string containsPrefix = "";
SgStatement *st_ps = getParentStat(st);
if (st_ps->variant() == PROC_HEDR || st_ps->variant() == PROG_HEDR || st_ps->variant() == FUNC_HEDR)
containsPrefix = st_ps->symbol()->identifier() + string(".");
extendRegionInfo(st, startEnd, lines_);
if (st->variant() == PROC_STAT)
{
string fullName = st->symbol()->identifier();
//check contains
if (mapFuncs.find(containsPrefix + fullName) != mapFuncs.end())
fullName = containsPrefix + fullName;
funcCallFromReg.insert(fullName);
}
for (int z = 0; z < 3; ++z)
findFuncCalls(st->expr(z), funcCallFromReg, containsPrefix, mapFuncs);
}
static void fillArrayNamesInReg(set<string> &usedArrayInRegion, SgExpression *exp)
{
if (exp)
{
if (exp->variant() == ARRAY_REF && OriginalSymbol(exp->symbol()))
usedArrayInRegion.insert(OriginalSymbol(exp->symbol())->identifier());
fillArrayNamesInReg(usedArrayInRegion, exp->lhs());
fillArrayNamesInReg(usedArrayInRegion, exp->rhs());
}
}
static bool filterUserDirectives(set<string> &usedArrayInRegion, vector<Statement*> &userDvmDirs, vector<Statement*> &userDvmDirsF)
{
vector<Statement*> filtered;
bool changed = false;
for (auto &distr : userDvmDirs)
{
set<string> usedIndir;
for (int i = 0; i < 3; ++i)
fillArrayNamesInReg(usedIndir, distr->GetOriginal()->expr(i));
bool ok = false;
for (auto &elem : usedIndir)
{
if (usedArrayInRegion.find(elem) != usedArrayInRegion.end())
{
ok = true;
break;
}
}
if (ok)
{
usedArrayInRegion.insert(usedIndir.begin(), usedIndir.end());
userDvmDirsF.push_back(distr);
changed = true;
}
else
filtered.push_back(distr);
}
userDvmDirs = filtered;
return changed;
}
static void filterUserDirectives(ParallelRegion *currReg, set<string> usedArrayInRegion, vector<Statement*> userDvmDistrDirs,
vector<Statement*> userDvmAlignDirs, vector<Statement*> userDvmShadowDirs)
{
vector<Statement*> userDvmDistrDirsF;
vector<Statement*> userDvmAlignDirsF;
vector<Statement*> userDvmShadowDirsF;
bool changed = false;
do
{
changed = false;
bool ret = filterUserDirectives(usedArrayInRegion, userDvmDistrDirs, userDvmDistrDirsF);
changed = changed || ret;
ret = filterUserDirectives(usedArrayInRegion, userDvmAlignDirs, userDvmAlignDirsF);
changed = changed || ret;
ret = filterUserDirectives(usedArrayInRegion, userDvmShadowDirs, userDvmShadowDirsF);
changed = changed || ret;
} while (changed);
currReg->AddUserDirectives(userDvmDistrDirsF, DVM_DISTRIBUTE_DIR);
currReg->AddUserDirectives(userDvmAlignDirsF, DVM_ALIGN_DIR);
currReg->AddUserDirectives(userDvmShadowDirsF, DVM_SHADOW_DIR);
}
static void setExplicitFlag(const string &name, const map<string, FuncInfo*> &mapFuncs)
{
auto it = mapFuncs.find(name);
if (it != mapFuncs.end())
it->second->inRegion = 1;
}
static void fillDvmDirs(SgStatement *st, vector<Statement*> &userDvmDistrDirs, vector<Statement*> &userDvmAlignDirs,
vector<Statement*> &userDvmShadowDirs, vector<Statement*> &userDvmRealignDirs, vector<Statement*> &userDvmRedistrDirs,
vector<Statement*>& userDvmRealignDirsDef, vector<Statement*>& userDvmRedistrDirsDef,
const bool &regionStarted, const map<int, LoopGraph*> &allLoopsInFile)
{
switch (st->variant())
{
case DVM_VAR_DECL:
{
string unparsed = st->unparse();
convertToLower(unparsed);
if (unparsed.find("distribute") != string::npos)
userDvmDistrDirs.push_back(new Statement(st));
else if (unparsed.find("align") != string::npos)
userDvmAlignDirs.push_back(new Statement(st));
}
break;
case DVM_DISTRIBUTE_DIR:
userDvmDistrDirs.push_back(new Statement(st));
break;
case DVM_ALIGN_DIR:
userDvmAlignDirs.push_back(new Statement(st));
break;
case DVM_SHADOW_DIR:
userDvmShadowDirs.push_back(new Statement(st));
break;
case DVM_REALIGN_DIR:
if (regionStarted)
userDvmRealignDirs.push_back(new Statement(st));
userDvmRealignDirsDef.push_back(new Statement(st));
break;
case DVM_REDISTRIBUTE_DIR:
//skip 22.04.2020
/*if (regionStarted)
userDvmRedistrDirs.push_back(new Statement(st));
userDvmRedistrDirsDef.push_back(new Statement(st));*/
break;
case DVM_PARALLEL_ON_DIR:
if (st->lexNext()->variant() == FOR_NODE)
{
SgForStmt* forStat = (SgForStmt*)(st->lexNext());
auto it = allLoopsInFile.find(forStat->lineNumber());
if (it != allLoopsInFile.end())
it->second->userDvmDirective = new Statement(st);
}
break;
default:
break;
}
}
static void checkForEmpty(SgStatement *start, SgStatement *end, vector<Messages>& messagesForFile)
{
bool wasStarted = false;
int lineStarted = -1;
while (start != end)
{
if (start->variant() == CONTAINS_STMT)
break;
if (start->variant() == SPF_PARALLEL_REG_DIR)
{
wasStarted = true;
lineStarted = start->lineNumber();
}
else if (start->variant() == SPF_END_PARALLEL_REG_DIR)
{
if (wasStarted)
{
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Empty parallel regions is forbidden.");
__spf_printToLongBuf(messageR, R151);
messagesForFile.push_back(Messages(ERROR, lineStarted, messageR, messageE, 3021));
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}
else
{
wasStarted = false;
lineStarted = -1;
}
start = start->lexNext();
}
}
void fillRegionLines(SgFile *file, vector<ParallelRegion*> &regions, vector<Messages>& messagesForFile, vector<LoopGraph*> *loops, vector<FuncInfo*> *funcs)
{
map<string, FuncInfo*> mapFuncs;
if (funcs)
createMapOfFunc(*funcs, mapFuncs);
//fill default
ParallelRegion* defaultR = regions[0];
pair<int, int> lines;
//pair<SgStatement*, SgStatement*> startEndDef(NULL, NULL);
{
SgStatement* st = file->firstStatement();
st = st->lexNext();
lines = make_pair(st->lineNumber(), 0);
//startEndDef.first = st;
while (st)
{
st = st->lastNodeOfStmt();
lines.second = st->lineNumber();
//startEndDef.second = st;
st = st->lexNext();
}
}
defaultR->AddLines(lines, file->filename());
map<int, LoopGraph*> allLoopsInFile;
if (loops)
createMapLoopGraph(allLoopsInFile, loops);
//fill user's
int funcNum = file->numberOfFunctions();
string regionName = "";
map<string, pair<Statement*, Statement*>> startEnd;
map<string, pair<int, int>> lines_;
set<string> funcCallFromReg;
bool regionStarted = false;
vector<SgStatement*> toDel;
for (int i = 0; i < funcNum; ++i)
{
vector<Statement*> userDvmDistrDirs;
vector<Statement*> userDvmAlignDirs;
vector<Statement*> userDvmShadowDirs;
vector<Statement*> userDvmRealignDirs;
vector<Statement*> userDvmRedistrDirs;
vector<Statement*> userDvmRealignDirsDef;
vector<Statement*> userDvmRedistrDirsDef;
set<string> usedArrayInRegion;
SgStatement *st = file->functions(i);
SgStatement *lastNode = st->lastNodeOfStmt();
string containsPrefix = "";
SgStatement *st_cp = st->controlParent();
if (st_cp->variant() == PROC_HEDR || st_cp->variant() == PROG_HEDR || st_cp->variant() == FUNC_HEDR)
containsPrefix = st_cp->symbol()->identifier() + string(".");
const string funcName = containsPrefix + file->functions(i)->symbol()->identifier();
checkForEmpty(st, lastNode, messagesForFile);
while (st != NULL && st != lastNode)
{
if (st->variant() == CONTAINS_STMT)
break;
SgStatement *prev = st->lexPrev();
SgStatement *next = st->lexNext();
if (prev && prev->variant() == SPF_PARALLEL_REG_DIR)
{
SgStatement *data = prev;
regionStarted = true;
regionName = data->symbol()->identifier();
if (funcs)
{
auto itFunc = mapFuncs.find(funcName);
if (itFunc != mapFuncs.end())
{
itFunc->second->inRegion = 3;
itFunc->second->callRegions.insert(0);
}
}
}
if (next && next->variant() == SPF_END_PARALLEL_REG_DIR)
{
updateRegionInfo(st, startEnd, lines_, funcCallFromReg, mapFuncs);
SgStatement *data = next;
lines.second = data->lineNumber();
regionStarted = false;
if (regionName == "")
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto it = regionIdByName.find(regionName);
ParallelRegion *currReg = NULL;
if (it == regionIdByName.end())
{
it = regionIdByName.insert(it, make_pair(regionName, regionIdConuter));
currReg = new ParallelRegion(regionIdConuter, regionName);
regions.push_back(currReg);
regionByName[regionName] = currReg;
regionName = "";
regionIdConuter++;
}
else
currReg = regionByName[regionName];
if (currReg == NULL)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
extendRegionInfo(st, startEnd, lines_, true);
for (auto itRegInfo = startEnd.begin(); itRegInfo != startEnd.end(); ++itRegInfo)
currReg->AddLines(lines_[itRegInfo->first], itRegInfo->first, &itRegInfo->second);
for (auto &func : funcCallFromReg)
currReg->AddFuncCalls(func);
filterUserDirectives(currReg, usedArrayInRegion, userDvmRedistrDirs, userDvmRealignDirs, userDvmShadowDirs);
currReg->AddUserDirectives(userDvmRealignDirs, DVM_REALIGN_DIR);
currReg->AddUserDirectives(userDvmRedistrDirs, DVM_REDISTRIBUTE_DIR);
startEnd.clear();
lines_.clear();
funcCallFromReg.clear();
userDvmRealignDirs.clear();
userDvmRedistrDirs.clear();
usedArrayInRegion.clear();
}
if (regionStarted)
{
updateRegionInfo(st, startEnd, lines_, funcCallFromReg, mapFuncs);
for (int i = 0; i < 3; ++i)
fillArrayNamesInReg(usedArrayInRegion, st->expr(i));
}
fillDvmDirs(st, userDvmDistrDirs, userDvmAlignDirs, userDvmShadowDirs, userDvmRealignDirs, userDvmRealignDirs, userDvmRealignDirsDef, userDvmRealignDirsDef, regionStarted, allLoopsInFile);
if (st->variant() == DVM_SHADOW_GROUP_DIR || st->variant() == DVM_SHADOW_START_DIR || st->variant() == DVM_SHADOW_WAIT_DIR)
toDel.push_back(st);
st = st->lexNext();
}
//for default
defaultR->AddUserDirectives(userDvmDistrDirs, DVM_DISTRIBUTE_DIR);
defaultR->AddUserDirectives(userDvmAlignDirs, DVM_ALIGN_DIR);
defaultR->AddUserDirectives(userDvmShadowDirs, DVM_SHADOW_DIR);
defaultR->AddUserDirectives(userDvmRealignDirsDef, DVM_REALIGN_DIR);
defaultR->AddUserDirectives(userDvmRedistrDirsDef, DVM_REDISTRIBUTE_DIR);
}
vector<SgStatement*> modules;
findModulesInFile(file, modules);
regionStarted = false;
for (auto& mod : modules)
{
vector<Statement*> userDvmDistrDirs;
vector<Statement*> userDvmAlignDirs;
vector<Statement*> userDvmShadowDirs;
vector<Statement*> userDvmRealignDirs;
vector<Statement*> userDvmRedistrDirs;
vector<Statement*> userDvmRealignDirsDef;
vector<Statement*> userDvmRedistrDirsDef;
for (SgStatement* st = mod->lexNext(); st; st = st->lexNext())
{
if (isSgExecutableStatement(st))
break;
fillDvmDirs(st, userDvmDistrDirs, userDvmAlignDirs, userDvmShadowDirs, userDvmRealignDirs, userDvmRealignDirs, userDvmRealignDirsDef, userDvmRealignDirsDef, regionStarted, allLoopsInFile);
if (st->variant() == DVM_SHADOW_GROUP_DIR)
toDel.push_back(st);
}
//for default
defaultR->AddUserDirectives(userDvmDistrDirs, DVM_DISTRIBUTE_DIR);
defaultR->AddUserDirectives(userDvmAlignDirs, DVM_ALIGN_DIR);
defaultR->AddUserDirectives(userDvmShadowDirs, DVM_SHADOW_DIR);
defaultR->AddUserDirectives(userDvmRealignDirsDef, DVM_REALIGN_DIR);
defaultR->AddUserDirectives(userDvmRedistrDirsDef, DVM_REDISTRIBUTE_DIR);
}
for (auto& elem : toDel)
elem->deleteStmt();
}
static void getAllLoops(vector<LoopGraph*> &loopGraph, vector<LoopGraph*> &loops)
{
for (auto &elem : loopGraph)
loops.push_back(elem);
for (auto &elem : loopGraph)
getAllLoops(elem->children, loops);
}
void fillRegionLinesStep2(vector<ParallelRegion*> &regions, const map<string, vector<FuncInfo*>> &allFuncInfo, map<string, vector<LoopGraph*>> *loopGraph)
{
map<string, FuncInfo*> funcMap;
createMapOfFunc(allFuncInfo, funcMap);
for (int i = 0; i < regions.size(); ++i)
{
if (regions[i]->GetName() != "DEFAULT")
for (auto &func : regions[i]->GetFuncCalls())
setExplicitFlag(func, funcMap);
}
for (int i = 0; i < regions.size(); ++i)
{
if (regions[i]->GetName() != "DEFAULT")
{
set<string> uniqFuncCalls;
for (auto &elem : regions[i]->GetFuncCalls())
uniqFuncCalls.insert(elem);
bool wasChanged = 1;
while (wasChanged)
{
wasChanged = 0;
for (auto &uniqF : uniqFuncCalls)
{
auto func = funcMap.find(uniqF);
if (func != funcMap.end())
{
for (auto &calls : func->second->callsFrom)
{
auto it = uniqFuncCalls.find(calls);
if (it == uniqFuncCalls.end())
{
uniqFuncCalls.insert(it, calls);
wasChanged = 1;
}
}
}
}
}
string toPrint = "";
for (auto &elem : uniqFuncCalls)
{
auto it = funcMap.find(elem);
if (it != funcMap.end())
{
regions[i]->AddLines(it->second->linesNum, it->second->fileName);
regions[i]->AddFuncCallsToAllCalls(it->second);
if (it->second->inRegion == 0)
it->second->inRegion = 2;
it->second->callRegions.insert(i);
toPrint += elem + " ";
}
}
if (toPrint != "")
__spf_print(1, "[%s]: funcs: %s\n", regions[i]->GetName().c_str(), toPrint.c_str());
}
}
// remove default region if user's found
if (regions.size() > 1)
{
#ifdef _WIN32
removeFromCollection(regions[0]);
#endif
delete regions[0];
regions.erase(regions.begin());
}
bool changed = true;
while (changed)
{
changed = false;
for (auto &func : funcMap)
{
if (func.second->inRegion != 0)
continue;
for (auto &callsFrom : func.second->callsFrom)
{
auto it = funcMap.find(callsFrom);
if (it != funcMap.end())
{
if (it->second->inRegion > 0)
{
func.second->inRegion = 3;
func.second->callRegions.insert(0);
changed = true;
break;
}
else
func.second->callRegions.insert(0);
}
}
}
}
if (loopGraph)
{
//fill regions for loop
vector<LoopGraph*> loops;
for (auto loop : *loopGraph)
getAllLoops(loop.second, loops);
for (auto &loop : loops)
{
const int currLine = loop->lineNum < -1 ? loop->loop->localLineNumber() : loop->lineNum;
set<ParallelRegion*> allRegs = getAllRegionsByLine(regions, loop->fileName, currLine);
if (allRegs.size() == 1)
loop->region = *(allRegs.begin());
}
}
}
int printParalleRegions(const char *fileName, vector<ParallelRegion*> &regions)
{
FILE *file = fopen(fileName, "w");
if (file == NULL)
{
__spf_print(1, "can not open file %s\n", fileName);
return -1;
}
int num = 0;
for (auto &elem : regions)
{
fprintf(file, "*** #%d Parallel Region\n", num);
elem->print(file);
fprintf(file, "\n");
++num;
}
fclose(file);
return 0;
}
static int getIntVal(SgExpression *ex)
{
SgExpression* calc = CalculateInteger(ex->copyPtr());
if (calc->variant() == INT_VAL)
return calc->valueInteger();
else
return 0;
}
static void fillMultOp(SgExpression *ex, pair<string, pair<int, int>> &retVal)
{
const int var = ex->lhs()->variant();
if (var == INT_VAL || var == CONST_REF || var == MINUS_OP) // -+a * X
{
retVal.first = ex->rhs()->symbol()->identifier();
retVal.second.first = getIntVal(ex->lhs());
}
else if (var == VAR_REF) // X * -+a
{
retVal.first = ex->lhs()->symbol()->identifier();
retVal.second.first = getIntVal(ex->rhs());
}
}
static pair<string, pair<int, int>> parseExpression(SgExpression *ex)
{
pair<string, pair<int, int>> retVal;
if (ex)
{
if (ex->variant() == VAR_REF)
{
retVal.first = ex->symbol()->identifier();
retVal.second = make_pair(1, 0);
}
else if (ex->variant() == MULT_OP) // a * X
fillMultOp(ex, retVal);
else if (ex->variant() == ADD_OP || ex->variant() == SUBT_OP) // a * X +- b
{
int minus = (ex->variant() == ADD_OP) ? 1 : -1;
if (ex->lhs()->variant() == MULT_OP) // a * X +- b
{
fillMultOp(ex->lhs(), retVal);
retVal.second.second = getIntVal(ex->rhs()) * minus;
}
else if (ex->lhs()->variant() == INT_VAL) // b +- [a *] X
{
if (ex->rhs()->variant() == MULT_OP)
fillMultOp(ex->rhs(), retVal);
else
{
retVal.first = ex->rhs()->symbol()->identifier();
retVal.second.first = minus;
}
retVal.second.second = getIntVal(ex->lhs()) * minus;
}
else if (ex->lhs()->variant() == VAR_REF && ex->rhs()->variant()) // X +- b
{
retVal.first = ex->lhs()->symbol()->identifier();
retVal.second.first = 1;
retVal.second.second = getIntVal(ex->rhs()) * minus;
}
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
else if (ex->variant() == KEYWORD_VAL) // *
{
SgKeywordValExp* keyVal = (SgKeywordValExp*)ex;
if (keyVal->value())
retVal = make_pair(keyVal->value(), make_pair(0, 0));
}
else if (ex->variant() == DDOT || ex->variant() == INT_VAL || ex->variant() == CONST_REF) // ':' | 'digit' equal '*'
retVal = make_pair("*", make_pair(0, 0));
else
{
__spf_print(1, "align pattern: '%s'\n", ex->unparse());
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}
return retVal;
}
static void fillTemplate(SgExpression *ex, vector<pair<string, pair<int, int>>> &templateArray)
{
for (SgExpression *list = ex; list; list = list->rhs())
templateArray.push_back(parseExpression(list->lhs()));
}
static int getTemplateDemention(const string &val, const vector<pair<string, pair<int, int>>> &alignWithTemplate)
{
int ret = -1;
for (int k = 0; k < alignWithTemplate.size(); ++k)
{
if (alignWithTemplate[k].first == val)
{
ret = k;
break;
}
}
return ret;
}
static bool needToSkip(SgStatement* dir, vector<FuncInfo*> funcs)
{
bool retVal = false;
auto iterator = dir;
while (iterator && iterator->variant() != PROG_HEDR && iterator->variant() != PROC_HEDR && iterator->variant() != FUNC_HEDR)
iterator = iterator->controlParent();
if (iterator == NULL)
return retVal;
for (auto& elem : funcs)
{
if (elem->funcPointer->GetOriginal()->thebif == iterator->thebif)
{
if (elem->doNotAnalyze)
return true;
break;
}
}
return retVal;
}
bool buildGraphFromUserDirectives(const vector<Statement*> &userDvmAlignDirs, DIST::GraphCSR<int, double, attrType> &G,
DIST::Arrays<int> &allArrays, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
const set<DIST::Array*>& alignedArrays, set<DIST::Array*>& addedArrays,
const map<string, vector<FuncInfo*>>& funcsByFile)
{
if (userDvmAlignDirs.size())
{
bool cleaned = false;
int t = 0;
for (auto &dir : userDvmAlignDirs)
{
const string file = dir->GetFileNameIncludedTo();
if (SgFile::switchToFile(file) == -1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto it = funcsByFile.find(file);
if (needToSkip(dir->GetOriginal(), it == funcsByFile.end() ? vector<FuncInfo*>() : it->second));
continue;
vector<DIST::Array*> alignArrays;
vector<pair<string, pair<int, int>>> alignTemplate;
DIST::Array* alignWithArray = NULL;
vector<pair<string, pair<int, int>>> alignWithTemplate;
if (dir->expr(0) == NULL)
return true;
for (SgExpression *ex = dir->expr(0); ex; ex = ex->rhs())
{
SgExpression *val = ex->lhs();
if (val->variant() == ARRAY_REF && val->symbol())
{
DIST::Array *newValue = getArrayFromDeclarated(declaratedInStmt(val->symbol()), val->symbol()->identifier());
if (newValue)
alignArrays.push_back(newValue);
else
return true;
}
}
map<DIST::Array*, set<DIST::Array*>> realAlignArrayRefs;
for (auto &access : alignArrays)
getRealArrayRefs(access, access, realAlignArrayRefs[access], arrayLinksByFuncCalls);
set<DIST::Array*> realAlignArrayRefsSet;
for (auto &elem : realAlignArrayRefs)
realAlignArrayRefsSet.insert(elem.second.begin(), elem.second.end());
if (dir->expr(1))
fillTemplate(dir->expr(1), alignTemplate);
else if (dir->variant() == DVM_VAR_DECL)
fillTemplate(dir->expr(2)->lhs()->lhs(), alignTemplate);
else
return true;
if (dir->expr(2))
{
SgExpression *ex = dir->expr(2);
if (ex->variant() == EXPR_LIST && ex->lhs()->variant() == ALIGN_OP)
ex = ex->lhs()->rhs();
if (ex && ex->variant() == ARRAY_REF && ex->symbol())
{
alignWithArray = getArrayFromDeclarated(declaratedInStmt(ex->symbol()), ex->symbol()->identifier());
if (alignWithArray == NULL)
return true;
fillTemplate(ex->lhs(), alignWithTemplate);
}
else
return true;
}
else
return true;
string tmp;
for (auto& elem : realAlignArrayRefsSet)
tmp += elem->GetName() + " ";
__spf_print(1, " align array%s '%s' from user dir in line %d\n", (realAlignArrayRefsSet.size() == 1 ? "" : "s"), tmp.c_str(), dir->lineNumber());
__spf_print(1, " template align:\n");
for (int i = 0; i < alignTemplate.size(); ++i)
__spf_print(1, " -- %d: %s -- [%d, %d]\n", i, alignTemplate[i].first.c_str(), alignTemplate[i].second.first, alignTemplate[i].second.second);
__spf_print(1, " template align with:\n");
for (int i = 0; i < alignWithTemplate.size(); ++i)
__spf_print(1, " -- %d: %s -- [%d, %d]\n", i, alignWithTemplate[i].first.c_str(), alignWithTemplate[i].second.first, alignWithTemplate[i].second.second);
for (int i = 0; i < alignTemplate.size(); ++i)
{
if (alignTemplate[i].first != "*")
{
int dimT = getTemplateDemention(alignTemplate[i].first, alignWithTemplate);
if (dimT == -1)
continue;
for (auto& array : realAlignArrayRefsSet)
{
if (!array->IsNotDistribute())
{
if (alignWithArray->IsTemplate() && alignWithArray->GetShortName().find("_r") != string::npos)
continue;
//TODO:
/*if (alignedArrays.find(array) != alignedArrays.end())
continue;*/
addedArrays.insert(array);
if (!cleaned)
{
cleaned = true;
G.ClearGraphCSR();
}
DIST::AddArrayAccess(G, allArrays, array, alignWithArray, make_pair(i, dimT), 1.0, make_pair(make_pair(1, 0), alignWithTemplate[dimT].second), WW_link);
}
}
}
}
}
}
return false;
}
void calculateLinesOfCode(vector<ParallelRegion*> &allRegions)
{
for (auto &elem : allRegions)
{
auto allLines = elem->GetAllLines();
int lineCounter = 0;
for (auto &line : allLines)
for (auto &lineV : line.second)
lineCounter += (lineV.lines.second - lineV.lines.first);
__spf_print(1, " Count of lines in region '%s' = %d\n", elem->GetName().c_str(), lineCounter);
}
}

View File

@@ -0,0 +1,402 @@
#pragma once
#include <string>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include "../Distribution/DvmhDirective.h"
#include "../Distribution/GraphCSR.h"
#include "../Distribution/Distribution.h"
#include "../Utils/AstWrapper.h"
#if __SPF
#include "../Utils/SgUtils.h"
#endif
struct ParallelRegionLines
{
ParallelRegionLines()
{
lines = std::make_pair(-1, -1);
stats = std::make_pair<Statement*, Statement*>(NULL, NULL);
intervalBefore = std::make_pair<Statement*, Statement*>(NULL, NULL);
intervalAfter = std::make_pair<Statement*, Statement*>(NULL, NULL);
}
ParallelRegionLines(const std::pair<int, int> &lines) : lines(lines)
{
stats = std::make_pair<Statement*, Statement*>(NULL, NULL);
intervalBefore = std::make_pair<Statement*, Statement*>(NULL, NULL);
intervalAfter = std::make_pair<Statement*, Statement*>(NULL, NULL);
}
ParallelRegionLines(const std::pair<int, int> &lines, const std::pair<Statement*, Statement*> stats) : lines(lines), stats(stats)
{
intervalBefore = std::make_pair<Statement*, Statement*>(NULL, NULL);
intervalAfter = std::make_pair<Statement*, Statement*>(NULL, NULL);
}
bool operator==(const ParallelRegionLines &regionLines) const { return lines == regionLines.lines && stats == regionLines.stats; }
bool operator<(const ParallelRegionLines &otherLines) const { return lines.first < otherLines.lines.first; }
void print(FILE *fileOut)
{
fprintf(fileOut, " [%d -- %d]", lines.first, lines.second);
if (stats.first && stats.second)
fprintf(fileOut, " explicit\n");
else
fprintf(fileOut, "\n");
}
bool isImplicit() const { return stats.first == NULL || stats.second == NULL; }
// <start, end> lines
std::pair<int, int> lines;
// <start, end> stats
std::pair<Statement*, Statement*> stats;
// <start, end> interval
std::pair<Statement*, Statement*> intervalBefore;
std::pair<Statement*, Statement*> intervalAfter;
};
#if __SPF
struct ParallelRegionArray
{
private:
std::string name;
std::string fileName;
SgSymbol *origSymbol;
SgSymbol *copySymbol;
std::vector<SgStatement*> declStatements;
std::vector<ParallelRegionLines> allLines;
public:
explicit ParallelRegionArray(const std::string &name, const std::string &fileName, SgSymbol *origSymbol, SgSymbol *copySymbol,
const ParallelRegionLines &lines, std::vector<SgStatement*> &declStatements) :
name(name), fileName(fileName), origSymbol(origSymbol), copySymbol(copySymbol), declStatements(declStatements)
{
allLines.push_back(lines);
}
const std::string& getName() const { return name; }
const std::string& getFileName() const { return fileName; }
SgSymbol* getOrigSymbol() const { return origSymbol; }
SgSymbol* getCopySymbol() const { return copySymbol; }
const std::vector<SgStatement*>& getDeclStatements() const { return declStatements; }
const std::vector<ParallelRegionLines>& getAllLines() const { return allLines; }
void addLines(const ParallelRegionLines &newLines)
{
for (auto &lines : allLines)
if (lines == newLines)
return;
allLines.push_back(newLines);
}
void setCopySymbol(SgSymbol *copySymbol) { this->copySymbol = copySymbol; }
};
#endif
struct ParallelRegion
{
public:
ParallelRegion(const uint64_t regionId, const std::string &originalName) : regionId(regionId), originalName(originalName) { }
ParallelRegion(const ParallelRegion &copy) : allArrays(copy.allArrays), G(copy.G), reducedG(copy.reducedG), dataDirectives(copy.dataDirectives)
{
regionId = copy.regionId;
originalName = copy.originalName;
lines = copy.lines;
functionsCall = copy.functionsCall;
currentVariant = copy.currentVariant;
}
int AddLines(const std::pair<int, int> &linesToAdd, const std::string &file, const std::pair<Statement*, Statement*> *startEnd = NULL)
{
if (linesToAdd.first > linesToAdd.second)
return -1;
auto it = lines.find(file);
if (it == lines.end())
it = lines.insert(it, make_pair(file, std::vector<ParallelRegionLines>()));
if (startEnd)
it->second.push_back(ParallelRegionLines(linesToAdd, *startEnd));
else
it->second.push_back(ParallelRegionLines(linesToAdd));
return 0;
}
void AddFuncCalls(const std::string &func) { functionsCall.insert(func); }
#if __SPF
void AddFuncCallsToAllCalls(FuncInfo *func) { allFunctionsCall.insert(func); }
#endif
uint64_t GetId() const { return regionId; }
const std::string& GetName() const { return originalName; }
const std::map<std::string, std::vector<ParallelRegionLines>>& GetAllLines() const { return lines; }
std::map<std::string, std::vector<ParallelRegionLines>>& GetAllLinesToModify() { return lines; }
const std::vector<ParallelRegionLines>* GetLines(const std::string &file) const
{
auto it = lines.find(file);
if (it == lines.end())
return NULL;
else
return &(it->second);
}
const ParallelRegionLines* GetLinesByLine(const std::string &file, const int line) const
{
auto fileLines = GetLines(file);
if (fileLines)
for (auto &lines : *fileLines)
if (lines.lines.first <= line && line <= lines.lines.second)
return &lines;
return NULL;
}
const DIST::GraphCSR<int, double, attrType>& GetGraph() const { return G; }
DIST::GraphCSR<int, double, attrType>& GetGraphToModify() { return G; }
const DIST::GraphCSR<int, double, attrType>& GetReducedGraph() const { return reducedG; }
DIST::GraphCSR<int, double, attrType>& GetReducedGraphToModify() { return reducedG; }
const DIST::Arrays<int>& GetAllArrays() const { return allArrays; }
DIST::Arrays<int>& GetAllArraysToModify() { return allArrays; }
void SetCurrentVariant(const std::vector<int> &newVariant) { currentVariant = newVariant; }
const std::vector<int>& GetCurrentVariant() const { return currentVariant; }
const DataDirective& GetDataDir() const { return dataDirectives; }
DataDirective& GetDataDirToModify() { return dataDirectives; }
const std::set<std::string>& GetFuncCalls() const { return functionsCall; }
#if __SPF
const std::set<FuncInfo*>& GetAllFuncCalls() const { return allFunctionsCall; }
const std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>>& GetUsedLocalArrays() const { return usedLocalArrays; }
const std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>>& GetUsedCommonArrays() const { return usedCommonArrays; }
void AddUsedLocalArray(FuncInfo *func, DIST::Array *array, const ParallelRegionLines &lines)
{
auto it = usedLocalArrays.find(func);
if (it == usedLocalArrays.end())
it = usedLocalArrays.insert(it, std::make_pair(func, std::map<DIST::Array*, std::vector<ParallelRegionLines>>()));
auto itt = it->second.find(array);
if (itt == it->second.end())
itt = it->second.insert(itt, std::make_pair(array, std::vector<ParallelRegionLines>()));
for (auto &curLines : itt->second)
if (curLines == lines)
return;
itt->second.push_back(lines);
}
void AddUsedCommonArray(FuncInfo *func, DIST::Array *array, const ParallelRegionLines &lines)
{
auto it = usedCommonArrays.find(func);
if (it == usedCommonArrays.end())
it = usedCommonArrays.insert(it, std::make_pair(func, std::map<DIST::Array*, std::vector<ParallelRegionLines>>()));
auto itt = it->second.find(array);
if (itt == it->second.end())
itt = it->second.insert(itt, std::make_pair(array, std::vector<ParallelRegionLines>()));
for (auto &curLines : itt->second)
if (curLines == lines)
return;
itt->second.push_back(lines);
}
#endif
bool HasThisLine(const int line, const std::string &file) const
{
bool retVal = false;
auto it = lines.find(file);
if (it != lines.end())
{
for (int i = 0; i < it->second.size(); ++i)
{
if (it->second[i].lines.first <= line && it->second[i].lines.second >= line)
{
retVal = true;
break;
}
}
}
return retVal;
}
std::string toString()
{
std::string retVal = "";
retVal += "#" + std::to_string(regionId);
retVal += "#" + originalName;
retVal += "#" + std::to_string(lines.size());
for (auto it = lines.begin(); it != lines.end(); ++it)
{
retVal += "|" + it->first + "|";
retVal += std::to_string(it->second.size());
for (int i = 0; i < it->second.size(); ++i)
retVal += "#" + std::to_string(it->second[i].lines.first) + "#" + std::to_string(it->second[i].lines.second);
}
const std::set<DIST::Array*> &arrays = allArrays.GetArrays();
retVal += "#" + std::to_string(arrays.size());
//create map<array_address, DIST::Array_toString()>
for (auto it = arrays.begin(); it != arrays.end(); ++it)
{
retVal += "#" + std::to_string((long long)(*it));
retVal += "#" + (*it)->toString();
}
retVal += "#" + std::to_string(dataDirectives.alignRules.size());
for (int i = 0; i < dataDirectives.alignRules.size(); ++i)
retVal += dataDirectives.alignRules[i].toString();
return retVal;
}
void CleanData()
{
reducedG.ClearGraphCSR();
currentVariant.clear();
dataDirectives.distrRules.clear();
dataDirectives.alignRules.clear();
}
void print(FILE *fileOut)
{
fprintf(fileOut, " regionId %lld\n", regionId);
fprintf(fileOut, " originalName '%s'\n", originalName.c_str());
fprintf(fileOut, " functions call from %d:\n", (int)functionsCall.size());
for (auto &func : functionsCall)
fprintf(fileOut, " '%s'\n", func.c_str());
fprintf(fileOut, " total lines %d:\n", (int)lines.size());
for (auto &line : lines)
{
fprintf(fileOut, " in file '%s':\n", line.first.c_str());
for (auto &elem : line.second)
{
fprintf(fileOut, " ");
elem.print(fileOut);
}
}
}
void AddUserDirectives(const std::vector<Statement*> &dirs, const int type)
{
if (dirs.size() == 0)
return;
if (type == DVM_DISTRIBUTE_DIR || type == DVM_VAR_DECL)
userDvmDistrDirs.insert(userDvmDistrDirs.end(), dirs.begin(), dirs.end());
else if (type == DVM_ALIGN_DIR)
userDvmAlignDirs.insert(userDvmAlignDirs.end(), dirs.begin(), dirs.end());
else if (type == DVM_SHADOW_DIR)
userDvmShadowDirs.insert(userDvmShadowDirs.end(), dirs.begin(), dirs.end());
else if (type == DVM_REALIGN_DIR)
userDvmRealignDirs.insert(userDvmRealignDirs.end(), dirs.begin(), dirs.end());
else if (type == DVM_REDISTRIBUTE_DIR)
userDvmRedistrDirs.insert(userDvmRedistrDirs.end(), dirs.begin(), dirs.end());
}
const std::vector<Statement*>* GetUsersDirecites(const int type) const
{
if (type == DVM_DISTRIBUTE_DIR || type == DVM_VAR_DECL)
return &userDvmDistrDirs;
else if (type == DVM_ALIGN_DIR)
return &userDvmAlignDirs;
else if (type == DVM_SHADOW_DIR)
return &userDvmShadowDirs;
else if (type == DVM_REALIGN_DIR)
return &userDvmRealignDirs;
else if (type == DVM_REDISTRIBUTE_DIR)
return &userDvmRedistrDirs;
else
return NULL;
}
bool HasUserDvmDirs() const
{
return userDvmDistrDirs.size() != 0 ||
userDvmAlignDirs.size() != 0 ||
userDvmShadowDirs.size() != 0 ||
userDvmRealignDirs.size() != 0 ||
userDvmRedistrDirs.size() != 0;
}
#if __SPF
void ClearUserDirs()
{
ClearVector(userDvmDistrDirs);
ClearVector(userDvmAlignDirs);
ClearVector(userDvmShadowDirs);
ClearVector(userDvmRealignDirs);
ClearVector(userDvmRedistrDirs);
}
#endif
private:
uint64_t regionId;
//name in program
std::string originalName;
// file -> lines info
std::map<std::string, std::vector<ParallelRegionLines>> lines;
std::set<std::string> functionsCall;
#if __SPF
// for RESOLVE_PAR_REGIONS
std::set<FuncInfo*> allFunctionsCall;
std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>> usedLocalArrays; // func -> array -> lines
std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>> usedCommonArrays; // func -> array -> lines
//
#endif
// for LOOP_ANALYZER_DATA_DIST
DIST::GraphCSR<int, double, attrType> G;
DIST::Arrays<int> allArrays;
DIST::GraphCSR<int, double, attrType> reducedG;
//
//for directive creating
DataDirective dataDirectives;
std::vector<int> currentVariant;
//
std::vector<Statement*> userDvmDistrDirs;
std::vector<Statement*> userDvmAlignDirs;
std::vector<Statement*> userDvmShadowDirs;
std::vector<Statement*> userDvmRealignDirs;
std::vector<Statement*> userDvmRedistrDirs;
#if __SPF
void ClearVector(std::vector<Statement*> &toRem)
{
for (auto& elem : toRem)
{
if (SgFile::switchToFile(elem->fileName()))
;// printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
else
elem->deleteStmt();
}
toRem.clear();
}
#endif
};
ParallelRegion* getRegionById(const std::vector<ParallelRegion*>& regions, const uint64_t regionId);
ParallelRegion* getRegionByName(const std::vector<ParallelRegion*>& regions, const std::string& regionName);
ParallelRegion* getRegionByLine(const std::vector<ParallelRegion*>& regions, const std::string& file, const int line);
std::set<ParallelRegion*> getAllRegionsByLine(const std::vector<ParallelRegion*>& regions, const std::string& file, const int line);

View File

@@ -0,0 +1,12 @@
#pragma once
#include "ParRegions.h"
#include "../GraphCall/graph_calls.h"
#include "../GraphLoop/graph_loops.h"
void fillRegionLines(SgFile *file, std::vector<ParallelRegion*> &regions, std::vector<Messages>& messagesForFile, std::vector<LoopGraph*> *loops = NULL, std::vector<FuncInfo*> *funcs = NULL);
void fillRegionLinesStep2(std::vector<ParallelRegion*> &regions, const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, std::map<std::string, std::vector<LoopGraph*>> *loopGraph = NULL);
int printParalleRegions(const char *fileName, std::vector<ParallelRegion*> &regions);
bool buildGraphFromUserDirectives(const std::vector<Statement*> &userDvmAlignDirs, DIST::GraphCSR<int, double, attrType> &G, DIST::Arrays<int> &allArrays, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, const std::set<DIST::Array*>& alignedArrays, std::set<DIST::Array*>& addedArrays, const std::map<std::string, std::vector<FuncInfo*>>& funcsByFile);
void clearRegionStaticData();
void calculateLinesOfCode(std::vector<ParallelRegion*> &allRegions);

Some files were not shown because too many files have changed in this diff Show More