Compare commits
5 Commits
master
...
a6c361eb49
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6c361eb49 | ||
|
|
5f0baf3c0e | ||
| 4a8f9baeed | |||
|
|
d47c165e0a | ||
|
|
9c0a59b8ee |
80
.gitignore
vendored
80
.gitignore
vendored
@@ -1,80 +0,0 @@
|
|||||||
# Add any directories, files, or patterns you don't want to be tracked by version control
|
|
||||||
*.o
|
|
||||||
Sapfor/.idea/
|
|
||||||
Sapfor/cmake-build-debug/
|
|
||||||
Sapfor/.vs/
|
|
||||||
Sapfor/_bin/
|
|
||||||
Sapfor/_lib/
|
|
||||||
Sapfor/Inliner/x64/
|
|
||||||
Sapfor/Parser/x64/
|
|
||||||
Sapfor/SageLib/x64/
|
|
||||||
Sapfor/SageNewSrc/x64/
|
|
||||||
Sapfor/SageOldSrc/x64/
|
|
||||||
Sapfor/Sapfor/x64/
|
|
||||||
Sapfor/TransformCommonLib/x64/
|
|
||||||
Sapfor/TransformLib/x64/
|
|
||||||
Sapfor/TransformUtils/x64/
|
|
||||||
dvm/fdvm/trunk/.svn/
|
|
||||||
Sapfor/.svn/
|
|
||||||
sapfor/transformers
|
|
||||||
sapfor/transformers/.svn/
|
|
||||||
Sapfor/_src/boost
|
|
||||||
Sapfor/Sapfor/Sapfor.vcxproj.user
|
|
||||||
sapfor/analyzers/
|
|
||||||
sapfor/general/
|
|
||||||
sapfor/generators/
|
|
||||||
sapfor/idb/
|
|
||||||
sapfor/CMakeLists.txt
|
|
||||||
sapfor/experts/expert/
|
|
||||||
sapfor/experts/expert_maxim_last_version/
|
|
||||||
sapfor/experts/visualizer/
|
|
||||||
sapfor/.svn/
|
|
||||||
|
|
||||||
Sapfor/cmake-build-debug/
|
|
||||||
Sapfor/build/
|
|
||||||
Sapfor/Inliner/build/
|
|
||||||
Sapfor/Parser/build/
|
|
||||||
Sapfor/Sapfor/*.o
|
|
||||||
sapfor/transformers/ftransform/trunk/cmake-build-debug/
|
|
||||||
sapfor/transformers/ftransform/trunk/build/
|
|
||||||
sapfor/transformers/ftransform/trunk/parser/build/
|
|
||||||
**/.idea
|
|
||||||
|
|
||||||
dvm/cdvm/
|
|
||||||
dvm/cdvmh-clang/
|
|
||||||
dvm/driver/
|
|
||||||
dvm/general/
|
|
||||||
dvm/releases/
|
|
||||||
dvm/rts/
|
|
||||||
dvm/rts-dvmh/
|
|
||||||
dvm/tools/projectStructureForFortran/
|
|
||||||
dvm/tools/pppa/.svn
|
|
||||||
dvm/tools/Zlib/.svn
|
|
||||||
dvm/tools/predictor/
|
|
||||||
dvm/tools/omp-dbg/
|
|
||||||
dvm/tools/omp-otc/
|
|
||||||
dvm/tools/omp-pa/
|
|
||||||
dvm/CMakeLists.txt
|
|
||||||
dvm/.svn/
|
|
||||||
dvm/fdvm/branches/
|
|
||||||
Sapfor/TransformCommonLib/TransformCommonLib.vcxproj.user
|
|
||||||
Sapfor/SageOldSrc/SageOldSrc.vcxproj.user
|
|
||||||
Sapfor/SageNewSrc/SageNewSrc.vcxproj.user
|
|
||||||
Sapfor/SageLib/SageLib.vcxproj.user
|
|
||||||
Sapfor/Inliner/Inliner.vcxproj.user
|
|
||||||
Sapfor/TransformUtils/TransformUtils.vcxproj.user
|
|
||||||
Sapfor/Parser/Parser.vcxproj.user
|
|
||||||
.vscode/*
|
|
||||||
.vs/
|
|
||||||
**/**/.DS_Store
|
|
||||||
Sapfor/Sapc++/Sapc++/Sapc++.vcxproj.user
|
|
||||||
Sapfor/Sapc++/Sapc++/Sapc++.vcxproj.filters
|
|
||||||
Sapfor/Sapc++/Sapc++/Sapc++.vcxproj
|
|
||||||
Sapfor/Sapc++/Sapc++/x64/
|
|
||||||
Sapfor/Sapc++/x64/
|
|
||||||
|
|
||||||
/build
|
|
||||||
/cmake-build-debug
|
|
||||||
|
|
||||||
Sapfor/out/
|
|
||||||
Sapfor/_bin/*
|
|
||||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,6 +0,0 @@
|
|||||||
[submodule "projects/dvm"]
|
|
||||||
path = projects/dvm
|
|
||||||
url = https://dvmguest:dvmguest@dvm.keldysh.ru/dvm-system/dvm
|
|
||||||
[submodule "projects/libpredictor"]
|
|
||||||
path = projects/libpredictor
|
|
||||||
url = https://dvmguest:dvmguest@dvm.keldysh.ru/sapfor/dvm-perfm
|
|
||||||
533
CMakeLists.txt
533
CMakeLists.txt
@@ -1,533 +0,0 @@
|
|||||||
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(CMAKE_C_STANDARD 17)
|
|
||||||
|
|
||||||
set(fdvm_include projects/dvm/fdvmh/include/fdvmh/)
|
|
||||||
set(fdvm_sources projects/dvm/fdvmh/tools/fdvmh/)
|
|
||||||
set(sage_include_1 projects/dvm/fdvmh/include/sage/lib/)
|
|
||||||
set(sage_include_2 projects/dvm/fdvmh/include/sage/h/)
|
|
||||||
set(libdb_sources projects/dvm/fdvmh/lib/sage/db/)
|
|
||||||
set(sage_sources projects/dvm/fdvmh/lib/sage/sage/)
|
|
||||||
set(sagepp_sources projects/dvm/fdvmh/lib/sage/sage++/)
|
|
||||||
set(parser_sources projects/dvm/fdvmh/tools/parser/)
|
|
||||||
set(pppa_sources projects/dvm/pppa/src/)
|
|
||||||
set(zlib_sources projects/dvm/third-party/Zlib/)
|
|
||||||
set(libpred_sources projects/libpredictor/src/)
|
|
||||||
set(libpred_include projects/libpredictor/include/)
|
|
||||||
|
|
||||||
include_directories(src)
|
|
||||||
include_directories(src/Utils)
|
|
||||||
include_directories(src/SgUtils)
|
|
||||||
include_directories(src/Distribution)
|
|
||||||
include_directories(src/GraphCall)
|
|
||||||
include_directories(src/GraphLoop)
|
|
||||||
include_directories(src/Transformations/ExpressionSubstitution)
|
|
||||||
include_directories(src/Transformations)
|
|
||||||
|
|
||||||
#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})
|
|
||||||
#Libpredictor includes
|
|
||||||
include_directories(${libpred_include})
|
|
||||||
|
|
||||||
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
|
|
||||||
src/Utils/json.hpp)
|
|
||||||
|
|
||||||
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
|
|
||||||
src/PrivateAnalyzer/private_arrays_search.cpp
|
|
||||||
src/PrivateAnalyzer/private_arrays_search.h
|
|
||||||
src/PrivateAnalyzer/range_structures.cpp
|
|
||||||
src/PrivateAnalyzer/range_structures.h
|
|
||||||
src/PrivateAnalyzer/region.cpp
|
|
||||||
src/PrivateAnalyzer/region.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/DeadCodeRemoving/dead_code.cpp
|
|
||||||
src/Transformations/DeadCodeRemoving/dead_code.h)
|
|
||||||
set(TR_CP src/Transformations/CheckPoints/checkpoints.cpp
|
|
||||||
src/Transformations/CheckPoints/checkpoints.h)
|
|
||||||
set(TR_VECTOR src/Transformations/VectorAssignToLoop/array_assign_to_loop.cpp
|
|
||||||
src/Transformations/VectorAssignToLoop/array_assign_to_loop.h)
|
|
||||||
set(TR_ENDDO_LOOP src/Transformations/LoopEndDoConverter/enddo_loop_converter.cpp
|
|
||||||
src/Transformations/LoopEndDoConverter/enddo_loop_converter.h)
|
|
||||||
set(TR_LOOP_NEST src/Transformations/LoopNesting/loop_transform.cpp
|
|
||||||
src/Transformations/LoopNesting/loop_transform.h)
|
|
||||||
set(TR_LOOP_COMB src/Transformations/LoopCombining/loops_combiner.cpp
|
|
||||||
src/Transformations/LoopCombining/loops_combiner.h)
|
|
||||||
set(TR_LOOP_SPLIT src/Transformations/LoopSplitting/loops_splitter.cpp
|
|
||||||
src/Transformations/LoopSplitting/loops_splitter.h)
|
|
||||||
set(TR_LOOP_UNROLL src/Transformations/LoopUnrolling/loops_unrolling.cpp
|
|
||||||
src/Transformations/LoopUnrolling/loops_unrolling.h)
|
|
||||||
set(TR_PRIV_BR src/Transformations/PrivateArrayResizing/private_arrays_resizing.cpp
|
|
||||||
src/Transformations/PrivateArrayResizing/private_arrays_resizing.h)
|
|
||||||
set(TR_PRIV_DEL src/Transformations/PrivateArrayRemoving/private_removing.cpp
|
|
||||||
src/Transformations/PrivateArrayRemoving/private_removing.h)
|
|
||||||
set(TR_SWAP_ARR_DIMS src/Transformations/ArrayDimsSwapping/swap_array_dims.cpp
|
|
||||||
src/Transformations/ArrayDimsSwapping/swap_array_dims.h)
|
|
||||||
set(TR_FUNC_DUP src/Transformations/FunctionDuplication/uniq_call_chain_dup.cpp
|
|
||||||
src/Transformations/FunctionDuplication/uniq_call_chain_dup.h)
|
|
||||||
set(TR_FUNC_PURE src/Transformations/FunctionPurifying/function_purifying.cpp
|
|
||||||
src/Transformations/FunctionPurifying/function_purifying.h)
|
|
||||||
set(TR_GV src/Transformations/GlobalVariables/fix_common_blocks.cpp
|
|
||||||
src/Transformations/GlobalVariables/fix_common_blocks.h)
|
|
||||||
set(TR_CONV src/Transformations/ConvertToC/convert_to_c.cpp
|
|
||||||
src/Transformations/ConvertToC/convert_to_c.h)
|
|
||||||
set(TR_IMPLICIT_NONE src/Transformations/SetImplicitNone/set_implicit_none.cpp
|
|
||||||
src/Transformations/SetImplicitNone/set_implicit_none.h)
|
|
||||||
set(TR_REPLACE_ARRAYS_IN_IO src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp
|
|
||||||
src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.h)
|
|
||||||
set(TR_EXPR_TRANSFORM src/Transformations/ExpressionSubstitution/control_flow_graph_part.cpp
|
|
||||||
src/Transformations/ExpressionSubstitution/expr_transform.cpp
|
|
||||||
src/Transformations/ExpressionSubstitution/expr_transform.h)
|
|
||||||
set(TR_INLINER src/Transformations/FunctionInlining/inliner.cpp
|
|
||||||
src/Transformations/FunctionInlining/inliner.h)
|
|
||||||
set(TR_RENAME_SYMBOLS src/Transformations/RenameSymbols/rename_symbols.cpp
|
|
||||||
src/Transformations/RenameSymbols/rename_symbols.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}
|
|
||||||
${TR_EXPR_TRANSFORM}
|
|
||||||
${TR_INLINER}
|
|
||||||
${TR_RENAME_SYMBOLS})
|
|
||||||
|
|
||||||
set(CFG src/CFGraph/IR.cpp
|
|
||||||
src/CFGraph/IR.h
|
|
||||||
src/CFGraph/IR_domTree.cpp
|
|
||||||
src/CFGraph/IR_domTree.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
|
|
||||||
)
|
|
||||||
|
|
||||||
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(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(LOOP_ANALYZER src/LoopAnalyzer/allocations_prepoc.cpp
|
|
||||||
src/LoopAnalyzer/dep_analyzer.cpp
|
|
||||||
src/LoopAnalyzer/loop_analyzer.cpp
|
|
||||||
src/LoopAnalyzer/loop_analyzer.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(LIBPREDICTOR ${libpred_sources}/cluster.cpp
|
|
||||||
${libpred_sources}/predictor.cpp
|
|
||||||
${libpred_sources}/transfer.cpp
|
|
||||||
${libpred_sources}/utils.cpp
|
|
||||||
${libpred_include}/libpredict/predictor.h
|
|
||||||
${libpred_include}/internal/cluster.h
|
|
||||||
${libpred_include}/internal/transfer.h
|
|
||||||
${libpred_include}/internal/utils.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}
|
|
||||||
${GR_CALL}
|
|
||||||
${GR_LOOP}
|
|
||||||
${LOOP_ANALYZER}
|
|
||||||
${TRANSFORMS}
|
|
||||||
${PARALLEL_REG}
|
|
||||||
${PRIV}
|
|
||||||
${FDVM}
|
|
||||||
${OMEGA}
|
|
||||||
${UTILS}
|
|
||||||
${VERIF}
|
|
||||||
${VS_CALLS}
|
|
||||||
${MAIN}
|
|
||||||
${PREDICTOR}
|
|
||||||
${LIBPREDICTOR}
|
|
||||||
${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 ${TR_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 ${TR_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 ${TR_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\\Analyzer FILES ${PREDICTOR})
|
|
||||||
source_group (Predictor\\Library FILES ${LIBPREDICTOR})
|
|
||||||
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()
|
|
||||||
if(NOT CMAKE_BUILD_TYPE)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_subdirectory(projects/Fdvm)
|
|
||||||
|
|
||||||
add_definitions("-D __SPF")
|
|
||||||
add_definitions("-D _CRT_SECURE_NO_WARNINGS")
|
|
||||||
add_definitions("-D _CRT_NON_CONFORMING_SWPRINTFS")
|
|
||||||
|
|
||||||
add_subdirectory(projects/SageOldSrc)
|
|
||||||
add_subdirectory(projects/SageNewSrc)
|
|
||||||
add_subdirectory(projects/SageLib)
|
|
||||||
add_subdirectory(projects/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>)
|
|
||||||
10
README.md
10
README.md
@@ -1,14 +1,12 @@
|
|||||||
# Общие правила по работе с SAPFOR #
|
# Общие правила по работе с SAPFOR #
|
||||||
Перед началом работы с репозиторием необходимо выставить настройку git по автоматической замене LF -> CRLF
|
|
||||||
|
|
||||||
* либо командой git config --global core.autocrlf true
|
Инструкция по настройке и запуску находится в Вики
|
||||||
* либо командой git config --local core.autocrlf true
|
|
||||||
|
|
||||||
Инструкция по SAPFOR находится в Вики этого репозитория.
|
Инструкция по SPF директивам https://cloud.mail.ru/public/GddP/THZKwqjRY
|
||||||
|
|
||||||
Проект Диалоговой оболочки (Визуализатора): http://dvmh-server.ddns.net:3000/M/VisualSapfor
|
Проект Диалоговой оболчки https://bitbucket.org/02090095/visual_dvm_2020/src/master/
|
||||||
|
|
||||||
Инструкция для установки и настройки Диалоговой оболочки: https://cloud.mail.ru/public/NDxu/LJJhQgQUG
|
Инструкция для установки и настройки Диалоговой обочки https://cloud.mail.ru/public/NDxu/LJJhQgQUG
|
||||||
|
|
||||||
Правила оформления кода в проекте:
|
Правила оформления кода в проекте:
|
||||||
|
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
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.tx
|
|
||||||
file(GLOB FDVM_HEADERS ${fdvm_include}/*.h)
|
|
||||||
|
|
||||||
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
|
|
||||||
${FDVM_HEADERS})
|
|
||||||
|
|
||||||
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)
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
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
|
|
||||||
file(GLOB PARSER_HEADERS ${parser_sources}/*.h)
|
|
||||||
|
|
||||||
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
|
|
||||||
${PARSER_HEADERS})
|
|
||||||
|
|
||||||
# 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)
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
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 ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
|
|
||||||
include_directories(${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()
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
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
|
|
||||||
file(GLOB SAGE_HEADERS1 ${sage_include_1}/*.h)
|
|
||||||
file(GLOB SAGE_HEADERS2 ${sage_include_2}/*.h)
|
|
||||||
|
|
||||||
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
|
|
||||||
${SAGE_HEADERS1}
|
|
||||||
${SAGE_HEADERS2})
|
|
||||||
|
|
||||||
# if not default ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
|
|
||||||
include_directories(${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()
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
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 ()
|
|
||||||
|
|
||||||
file(GLOB SAGE_HEADERS1 ${sage_include_1}/*.h)
|
|
||||||
file(GLOB SAGE_HEADERS2 ${sage_include_2}/*.h)
|
|
||||||
|
|
||||||
# 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
|
|
||||||
${SAGE_HEADERS1}
|
|
||||||
${SAGE_HEADERS2})
|
|
||||||
|
|
||||||
# if not default ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
|
|
||||||
include_directories(${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()
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
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
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|x64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|x64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<VCProjectVersion>15.0</VCProjectVersion>
|
|
||||||
<ProjectGuid>{DF2410E0-8B0A-420D-AC01-5DAFC460C816}</ProjectGuid>
|
|
||||||
<RootNamespace>Sapc</RootNamespace>
|
|
||||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="Shared">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<IncludePath>..\..\src;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<IncludePath>..\..\src;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;__SPC;_CRT_NON_CONFORMING_SWPRINTFS;</PreprocessorDefinitions>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;__SPC;_CRT_NON_CONFORMING_SWPRINTFS;</PreprocessorDefinitions>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\..\src\DirectiveProcessing\directive_analyzer.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\DirectiveProcessing\directive_creator_base.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\DirectiveProcessing\remote_access_base.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\Distribution\Array.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\Distribution\CreateDistributionDirs.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\Distribution\Cycle.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\Distribution\Distribution.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\Distribution\DvmhDirectiveBase.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\Distribution\GraphCSR.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\GraphCall\graph_calls_base.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\GraphLoop\graph_loops_base.cpp" />
|
|
||||||
<ClCompile Include="..\..\src\Utils\utils.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="..\..\src\DirectiveProcessing\directive_analyzer.h" />
|
|
||||||
<ClInclude Include="..\..\src\Distribution\Array.h" />
|
|
||||||
<ClInclude Include="..\..\src\Distribution\Arrays.h" />
|
|
||||||
<ClInclude Include="..\..\src\Distribution\CreateDistributionDirs.h" />
|
|
||||||
<ClInclude Include="..\..\src\Distribution\Cycle.h" />
|
|
||||||
<ClInclude Include="..\..\src\Distribution\Distribution.h" />
|
|
||||||
<ClInclude Include="..\..\src\Distribution\DvmhDirective.h" />
|
|
||||||
<ClInclude Include="..\..\src\Distribution\DvmhDirectiveBase.h" />
|
|
||||||
<ClInclude Include="..\..\src\Distribution\GraphCSR.h" />
|
|
||||||
<ClInclude Include="..\..\src\GraphCall\graph_calls.h" />
|
|
||||||
<ClInclude Include="..\..\src\GraphLoop\graph_loops.h" />
|
|
||||||
<ClInclude Include="..\..\src\LoopAnalyzer\directive_creator.h" />
|
|
||||||
<ClInclude Include="..\..\src\LoopAnalyzer\remote_access.h" />
|
|
||||||
<ClInclude Include="..\..\src\LoopConverter\loop_transform.h" />
|
|
||||||
<ClInclude Include="..\..\src\ParallelizationRegions\ParRegions.h" />
|
|
||||||
<ClInclude Include="..\..\src\Sapfor.h" />
|
|
||||||
<ClInclude Include="..\..\src\Utils\utils.h" />
|
|
||||||
<ClInclude Include="..\..\src\VisualizerCalls\SendMessage.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="Исходные файлы">
|
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
|
||||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Файлы заголовков">
|
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
|
||||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Файлы ресурсов">
|
|
||||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
|
||||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Исходные файлы\Distribution">
|
|
||||||
<UniqueIdentifier>{803b433b-ef2b-461c-bcdf-40587ac27031}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Файлы заголовков\Distribution">
|
|
||||||
<UniqueIdentifier>{9bbb0a2e-36f6-4736-8fa2-3f260e2df36c}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Файлы заголовков\GraphCall">
|
|
||||||
<UniqueIdentifier>{ed7a5083-8582-4f54-bcf2-fd6d393bdae8}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Файлы заголовков\GraphLoop">
|
|
||||||
<UniqueIdentifier>{0fc93dbd-8ac8-47fe-a5c9-26ad308f0197}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Исходные файлы\GraphLoop">
|
|
||||||
<UniqueIdentifier>{c06f742b-74c2-454e-b221-fa3924b6b4a3}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Исходные файлы\ParallelRegions">
|
|
||||||
<UniqueIdentifier>{a7d01b3a-ec98-48a0-8ba8-982b9d886b74}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Исходные файлы\Utils">
|
|
||||||
<UniqueIdentifier>{e6073352-1994-4bd6-87ba-662199402c45}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Файлы заголовков\Utils">
|
|
||||||
<UniqueIdentifier>{b5cb7e95-4314-488a-abec-8aa3d48d490b}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Исходные файлы\GraphCall">
|
|
||||||
<UniqueIdentifier>{9da92901-a281-4cd6-b61c-0390a02b09a8}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Исходные файлы\DirectiveAnalyzer">
|
|
||||||
<UniqueIdentifier>{f9d091f4-532b-4572-9e9a-5f80b8e012c4}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Исходные файлы\LoopAnalyzer">
|
|
||||||
<UniqueIdentifier>{87d2a4f0-26c0-45a2-acd0-992c9f1be1bc}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Файлы заголовков\CodeConverter">
|
|
||||||
<UniqueIdentifier>{e59c7920-1b24-4a95-9890-192e90bc0181}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Файлы заголовков\VisualizerCalls">
|
|
||||||
<UniqueIdentifier>{b5e5bfbb-6553-4e1a-a4a1-b60f62307e26}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\..\_src\Distribution\CreateDistributionDirs.cpp">
|
|
||||||
<Filter>Исходные файлы\Distribution</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\_src\Distribution\Cycle.cpp">
|
|
||||||
<Filter>Исходные файлы\Distribution</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\_src\Distribution\Distribution.cpp">
|
|
||||||
<Filter>Исходные файлы\Distribution</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\_src\Distribution\DvmhDirectiveBase.cpp">
|
|
||||||
<Filter>Исходные файлы\Distribution</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\_src\Distribution\GraphCSR.cpp">
|
|
||||||
<Filter>Исходные файлы\Distribution</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\_src\GraphLoop\graph_loops_base.cpp">
|
|
||||||
<Filter>Исходные файлы\GraphLoop</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\_src\Utils\utils.cpp">
|
|
||||||
<Filter>Исходные файлы\Utils</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\_src\GraphCall\graph_calls_base.cpp">
|
|
||||||
<Filter>Исходные файлы\GraphCall</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\_src\Distribution\Array.cpp">
|
|
||||||
<Filter>Файлы заголовков\Distribution</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\_src\DirectiveProcessing\directive_analyzer.cpp">
|
|
||||||
<Filter>Исходные файлы\DirectiveAnalyzer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\_src\DirectiveProcessing\directive_creator_base.cpp">
|
|
||||||
<Filter>Исходные файлы\LoopAnalyzer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\_src\DirectiveProcessing\remote_access_base.cpp">
|
|
||||||
<Filter>Исходные файлы\LoopAnalyzer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="..\..\_src\Distribution\Array.h">
|
|
||||||
<Filter>Файлы заголовков\Distribution</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\Distribution\Arrays.h">
|
|
||||||
<Filter>Файлы заголовков\Distribution</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\Distribution\CreateDistributionDirs.h">
|
|
||||||
<Filter>Файлы заголовков\Distribution</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\Distribution\Cycle.h">
|
|
||||||
<Filter>Файлы заголовков\Distribution</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\Distribution\Distribution.h">
|
|
||||||
<Filter>Файлы заголовков\Distribution</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\Distribution\DvmhDirectiveBase.h">
|
|
||||||
<Filter>Файлы заголовков\Distribution</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\Distribution\GraphCSR.h">
|
|
||||||
<Filter>Файлы заголовков\Distribution</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\GraphCall\graph_calls.h">
|
|
||||||
<Filter>Файлы заголовков\GraphCall</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\ParallelizationRegions\ParRegions.h">
|
|
||||||
<Filter>Исходные файлы\ParallelRegions</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\GraphLoop\graph_loops.h">
|
|
||||||
<Filter>Файлы заголовков\GraphLoop</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\Distribution\DvmhDirective.h">
|
|
||||||
<Filter>Файлы заголовков\Distribution</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\Utils\utils.h">
|
|
||||||
<Filter>Файлы заголовков\Utils</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\Sapfor.h">
|
|
||||||
<Filter>Файлы заголовков</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\LoopAnalyzer\directive_creator.h">
|
|
||||||
<Filter>Исходные файлы\LoopAnalyzer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\LoopConverter\loop_transform.h">
|
|
||||||
<Filter>Файлы заголовков\CodeConverter</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\VisualizerCalls\SendMessage.h">
|
|
||||||
<Filter>Файлы заголовков\VisualizerCalls</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\LoopAnalyzer\remote_access.h">
|
|
||||||
<Filter>Исходные файлы\LoopAnalyzer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\_src\DirectiveProcessing\directive_analyzer.h">
|
|
||||||
<Filter>Исходные файлы\DirectiveAnalyzer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 16
|
|
||||||
VisualStudioVersion = 16.0.29411.108
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "server\server.vcxproj", "{1D412171-922E-430B-B11C-38E29A98EC62}"
|
|
||||||
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
|
|
||||||
{1D412171-922E-430B-B11C-38E29A98EC62}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{1D412171-922E-430B-B11C-38E29A98EC62}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{1D412171-922E-430B-B11C-38E29A98EC62}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{1D412171-922E-430B-B11C-38E29A98EC62}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{1D412171-922E-430B-B11C-38E29A98EC62}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{1D412171-922E-430B-B11C-38E29A98EC62}.Release|x64.Build.0 = Release|x64
|
|
||||||
{1D412171-922E-430B-B11C-38E29A98EC62}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{1D412171-922E-430B-B11C-38E29A98EC62}.Release|x86.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {480AF568-6C59-432A-95B1-CBE56AF6FD27}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 117 KiB |
@@ -1,19 +0,0 @@
|
|||||||
//{{NO_DEPENDENCIES}}
|
|
||||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Microsoft Visual C++.
|
|
||||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> server.rc
|
|
||||||
//
|
|
||||||
#define IDI_ICON1 101
|
|
||||||
#define IDI_ICON2 102
|
|
||||||
#define IDI_ICON3 103
|
|
||||||
#define IDB_PNG1 104
|
|
||||||
|
|
||||||
// Next default values for new objects
|
|
||||||
//
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 105
|
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
// Microsoft Visual C++ generated resource script.
|
|
||||||
//
|
|
||||||
#pragma code_page(65001)
|
|
||||||
|
|
||||||
#include "resource.h"
|
|
||||||
|
|
||||||
#define APSTUDIO_READONLY_SYMBOLS
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Generated from the TEXTINCLUDE 2 resource.
|
|
||||||
//
|
|
||||||
#include "winres.h"
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
#undef APSTUDIO_READONLY_SYMBOLS
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Русский (Россия) resources
|
|
||||||
|
|
||||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
|
|
||||||
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
|
|
||||||
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// TEXTINCLUDE
|
|
||||||
//
|
|
||||||
|
|
||||||
1 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"resource.h\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
2 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"#include ""winres.h""\r\n"
|
|
||||||
"\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
3 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"\r\n"
|
|
||||||
"\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
#endif // APSTUDIO_INVOKED
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Icon
|
|
||||||
//
|
|
||||||
|
|
||||||
// Icon with lowest ID value placed first to ensure application icon
|
|
||||||
// remains consistent on all systems.
|
|
||||||
IDI_ICON3 ICON "icon3.ico"
|
|
||||||
|
|
||||||
#endif // Русский (Россия) resources
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef APSTUDIO_INVOKED
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Generated from the TEXTINCLUDE 3 resource.
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
#endif // not APSTUDIO_INVOKED
|
|
||||||
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|x64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|x64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
|
||||||
<ProjectGuid>{1D412171-922E-430B-B11C-38E29A98EC62}</ProjectGuid>
|
|
||||||
<RootNamespace>server</RootNamespace>
|
|
||||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="Shared">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<TargetName>Visualizer_2</TargetName>
|
|
||||||
<IncludePath>C:\local\boost_1_74_0;$(IncludePath)</IncludePath>
|
|
||||||
<LibraryPath>C:\local\boost_1_74_0\lib64-msvc-14.2;$(LibraryPath)</LibraryPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<TargetName>Visualizer_2</TargetName>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
|
|
||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="resource.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ResourceCompile Include="server.rc" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Image Include="icon3.ico" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\..\..\src\Server\checkUniq.cpp" />
|
|
||||||
<ClCompile Include="..\..\..\src\Server\server.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="Исходные файлы">
|
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
|
||||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Файлы заголовков">
|
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
|
||||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Файлы ресурсов">
|
|
||||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
|
||||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="resource.h">
|
|
||||||
<Filter>Файлы заголовков</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ResourceCompile Include="server.rc">
|
|
||||||
<Filter>Файлы ресурсов</Filter>
|
|
||||||
</ResourceCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Image Include="icon3.ico">
|
|
||||||
<Filter>Файлы ресурсов</Filter>
|
|
||||||
</Image>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\..\..\src\Server\checkUniq.cpp">
|
|
||||||
<Filter>Исходные файлы</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\src\Server\server.cpp">
|
|
||||||
<Filter>Исходные файлы</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
Submodule projects/dvm deleted from 4d4041a081
Submodule projects/libpredictor deleted from d0772cdb57
@@ -1,10 +0,0 @@
|
|||||||
fdvm_include=dvm/fdvmh/include/fdvmh/
|
|
||||||
fdvm_sources=dvm/fdvmh/tools/fdvmh/
|
|
||||||
sage_include_1=dvm/fdvmh/include/sage/lib/
|
|
||||||
sage_include_2=dvm/fdvmh/include/sage/h/
|
|
||||||
libdb_sources=dvm/fdvmh/lib/sage/db/
|
|
||||||
sage_sources=dvm/fdvmh/lib/sage/sage/
|
|
||||||
sagepp_sources=dvm/fdvmh/lib/sage/sage++/
|
|
||||||
parser_sources=dvm/fdvmh/tools/parser/
|
|
||||||
pppa_sources=dvm/pppa/src/
|
|
||||||
zlib_sources=dvm/third-party/Zlib/
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,160 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "IR.h"
|
|
||||||
#include "IR_domTree.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;
|
|
||||||
BasicBlock* directDominator = NULL;
|
|
||||||
//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 addInstruction(IR_Block* item);
|
|
||||||
void addPrev(BasicBlock* prev_) { prev.push_back(prev_); }
|
|
||||||
void addNext(BasicBlock* next_) { next.push_back(next_); }
|
|
||||||
void setDom(BasicBlock* dom) { directDominator = dom; }
|
|
||||||
|
|
||||||
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; }
|
|
||||||
BasicBlock* getDom() const
|
|
||||||
{
|
|
||||||
return directDominator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
bool withDominators = 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, bool withDominators = true) :
|
|
||||||
atLeastOneIterInLoop(atLeastOneIterInLoop), withRD(withRD), withRegisters(withRegisters), withDVM(withDVM), withSPF(withSPF),
|
|
||||||
withCallsInBlocks(withCallsInBlocks), withCallFrom(withCallFrom), withDominators(withDominators)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
void removedUnreachableBlocks(std::vector<SAPFOR::BasicBlock*>& blocks);
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "data_flow.h"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "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"
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "backward_data_flow.h"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include<vector>
|
|
||||||
#include<set>
|
|
||||||
|
|
||||||
#include "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"
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "data_flow.h"
|
|
||||||
|
|
||||||
#include<vector>
|
|
||||||
#include<set>
|
|
||||||
|
|
||||||
#include "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();
|
|
||||||
}
|
|
||||||
1615
src/CFGraph/IR.cpp
1615
src/CFGraph/IR.cpp
File diff suppressed because it is too large
Load Diff
346
src/CFGraph/IR.h
346
src/CFGraph/IR.h
@@ -1,346 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "CFGraph.h"
|
|
||||||
#include "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, 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);
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
#include "dvm.h"
|
|
||||||
#include "IR_domTree.h"
|
|
||||||
|
|
||||||
namespace SAPFOR {
|
|
||||||
void DominatorFinder::DFS(BasicBlock* v, int parent_num) {
|
|
||||||
dfs_num[v] = n;
|
|
||||||
vertex[n] = n;
|
|
||||||
semi[n] = n;
|
|
||||||
label[n] = n;
|
|
||||||
ancestor[n] = -1;
|
|
||||||
parent[n] = parent_num;
|
|
||||||
vertices[n++] = v;
|
|
||||||
|
|
||||||
for (const auto& w : v->getNext()) {
|
|
||||||
if (dfs_num[w] == -1)
|
|
||||||
DFS(w, dfs_num[v]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DominatorFinder::Compress(int v) {
|
|
||||||
if (ancestor[ancestor[v]] != -1) {
|
|
||||||
Compress(ancestor[v]);
|
|
||||||
|
|
||||||
if (semi[label[ancestor[v]]] < semi[label[v]])
|
|
||||||
label[v] = label[ancestor[v]];
|
|
||||||
ancestor[v] = ancestor[ancestor[v]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int DominatorFinder::Eval(int v) {
|
|
||||||
if (ancestor[v] == -1)
|
|
||||||
return v;
|
|
||||||
|
|
||||||
Compress(v);
|
|
||||||
return label[v];
|
|
||||||
}
|
|
||||||
|
|
||||||
void DominatorFinder::Link(int v, int w) {
|
|
||||||
ancestor[w] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
DominatorFinder::DominatorFinder(std::vector<BasicBlock*>& blocks) {
|
|
||||||
if (blocks.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
entry = blocks[0];
|
|
||||||
n = 0;
|
|
||||||
|
|
||||||
for (auto block : blocks)
|
|
||||||
dfs_num[block] = -1;
|
|
||||||
|
|
||||||
int max_size = blocks.size();
|
|
||||||
vertices.resize(max_size);
|
|
||||||
parent.assign(max_size, -1);
|
|
||||||
semi.assign(max_size, -1);
|
|
||||||
vertex.assign(max_size, -1);
|
|
||||||
ancestor.assign(max_size, -1);
|
|
||||||
label.assign(max_size, -1);
|
|
||||||
bucket.resize(max_size);
|
|
||||||
|
|
||||||
DFS(entry, -1);
|
|
||||||
|
|
||||||
for (int i = n - 1; i > 0; --i) {
|
|
||||||
int w = vertex[i];
|
|
||||||
|
|
||||||
for (BasicBlock* v : vertices[w]->getPrev()) {
|
|
||||||
if (dfs_num[v] == -1)
|
|
||||||
continue;
|
|
||||||
int u = Eval(dfs_num[v]);
|
|
||||||
|
|
||||||
if (semi[u] < semi[w])
|
|
||||||
semi[w] = semi[u];
|
|
||||||
}
|
|
||||||
|
|
||||||
bucket[vertex[semi[w]]].push_back(w);
|
|
||||||
Link(parent[w], w);
|
|
||||||
|
|
||||||
for (int v : bucket[parent[w]])
|
|
||||||
{
|
|
||||||
int u = Eval(v);
|
|
||||||
if (semi[u] < semi[v])
|
|
||||||
vertices[v]->setDom(vertices[u]);
|
|
||||||
else
|
|
||||||
vertices[v]->setDom(vertices[parent[w]]);
|
|
||||||
}
|
|
||||||
bucket[parent[w]].clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 1; i < n; ++i) {
|
|
||||||
int w = vertex[i];
|
|
||||||
|
|
||||||
if (vertices[w]->getDom() != vertices[vertex[semi[w]]])
|
|
||||||
vertices[w]->setDom(vertices[w]->getDom()->getDom());
|
|
||||||
}
|
|
||||||
|
|
||||||
entry->setDom(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void buildDominatorTree(std::vector<BasicBlock*>& blocks) {
|
|
||||||
DominatorFinder finder(blocks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "CFGraph.h"
|
|
||||||
|
|
||||||
// Lengauer, Thomas. A fast algorithm for finding dominators in a flowgraph / Thomas Lengauer, Robert Endre Tarjan
|
|
||||||
// ACM Transactions on Programming Languages and Systems (TOPLAS). <20> 1979. <20> Vol. 1, no. 1. <20> Pp. 121<32>141.
|
|
||||||
|
|
||||||
namespace SAPFOR {
|
|
||||||
|
|
||||||
class BasicBlock;
|
|
||||||
|
|
||||||
class DominatorFinder {
|
|
||||||
private:
|
|
||||||
BasicBlock* entry;
|
|
||||||
std::vector<BasicBlock*> vertices;
|
|
||||||
std::unordered_map<BasicBlock*, int> dfs_num;
|
|
||||||
std::vector<int> parent, semi, vertex, ancestor, label;
|
|
||||||
std::vector<std::vector<int>> bucket;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
void DFS(BasicBlock* v, int parent_num);
|
|
||||||
void Compress(int v);
|
|
||||||
int Eval(int v);
|
|
||||||
void Link(int v, int w);
|
|
||||||
|
|
||||||
public:
|
|
||||||
DominatorFinder(std::vector<BasicBlock*>& blocks);
|
|
||||||
};
|
|
||||||
|
|
||||||
void buildDominatorTree(std::vector<BasicBlock*>& blocks);
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,40 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include<unordered_map>
|
|
||||||
|
|
||||||
#include "SgUtils.h"
|
|
||||||
#include "CommonBlock.h"
|
|
||||||
#include "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();*/
|
|
||||||
@@ -1,761 +0,0 @@
|
|||||||
#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();
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "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);
|
|
||||||
@@ -1,539 +0,0 @@
|
|||||||
#include "errors.h"
|
|
||||||
#include "private_variables_analysis.h"
|
|
||||||
#include "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();
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#include "SgUtils.h"
|
|
||||||
#include "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);
|
|
||||||
@@ -1,882 +0,0 @@
|
|||||||
#include "CreateInterTree.h"
|
|
||||||
#include "SgUtils.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "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 *¤tSt)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "dvm.h"
|
|
||||||
|
|
||||||
#include "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);
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
#include "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 "graph_loops.h"
|
|
||||||
#include "directive_analyzer.h"
|
|
||||||
#include "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);
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "graph_loops.h"
|
|
||||||
|
|
||||||
void UniteNestedDirectives(std::vector<LoopGraph*> &loopGraph);
|
|
||||||
@@ -1,490 +0,0 @@
|
|||||||
#include "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 "errors.h"
|
|
||||||
#include "../LoopAnalyzer/loop_analyzer.h"
|
|
||||||
#include "directive_parser.h"
|
|
||||||
#include "directive_creator.h"
|
|
||||||
#include "SgUtils.h"
|
|
||||||
#include "../Sapfor.h"
|
|
||||||
#include "graph_loops_func.h"
|
|
||||||
#include "LoopNesting/loop_transform.h"
|
|
||||||
#include "expr_transform.h"
|
|
||||||
#include "graph_calls_func.h"
|
|
||||||
|
|
||||||
#include "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
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../Distribution/Distribution.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "graph_loops.h"
|
|
||||||
#include "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
@@ -1,536 +0,0 @@
|
|||||||
#include "leak_detector.h"
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include "dvm.h"
|
|
||||||
#include "directive_omp_parser.h"
|
|
||||||
#include "directive_parser.h"
|
|
||||||
|
|
||||||
#include "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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <string>
|
|
||||||
#include <set>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "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);
|
|
||||||
@@ -1,656 +0,0 @@
|
|||||||
#include "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 "SgUtils.h"
|
|
||||||
#include "../LoopAnalyzer/loop_analyzer.h"
|
|
||||||
#include "AstWrapper.h"
|
|
||||||
#include "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;
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <set>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "AstWrapper.h"
|
|
||||||
#include "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
@@ -1,63 +0,0 @@
|
|||||||
#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 removeDvmSpfDirectives(SgFile* file, bool removeDvm, bool removeSpf, 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
@@ -1,48 +0,0 @@
|
|||||||
#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);
|
|
||||||
@@ -1,772 +0,0 @@
|
|||||||
#include "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 "graph_calls.h"
|
|
||||||
#include "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
@@ -1,150 +0,0 @@
|
|||||||
#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
@@ -1,236 +0,0 @@
|
|||||||
#include "Array.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,830 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <climits>
|
|
||||||
#include "DvmhDirectiveBase.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "json.hpp"
|
|
||||||
|
|
||||||
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
|
|
||||||
#define JSON nlohmann::json
|
|
||||||
|
|
||||||
#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 ©)
|
|
||||||
{
|
|
||||||
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> deprecateToDistribute;
|
|
||||||
|
|
||||||
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> ®ions, 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);
|
|
||||||
deprecateToDistribute.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;
|
|
||||||
deprecateToDistribute[z] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GenUniqKey();
|
|
||||||
for (auto ® : regions)
|
|
||||||
containsInRegions.insert(reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
Array(const Array ©)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
deprecateToDistribute = copy.deprecateToDistribute;
|
|
||||||
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] || deprecateToDistribute[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] && !deprecateToDistribute[z])
|
|
||||||
{
|
|
||||||
newSizes.push_back(sizes[z]);
|
|
||||||
newSizesExpr.push_back(sizesExpr[z]);
|
|
||||||
newMappedDims.push_back(mappedDims[z]);
|
|
||||||
newDepr.push_back(deprecateToDistribute[z]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sizes = newSizes;
|
|
||||||
sizesExpr = newSizesExpr;
|
|
||||||
mappedDims = newMappedDims;
|
|
||||||
deprecateToDistribute = 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(); }
|
|
||||||
|
|
||||||
JSON toJson()
|
|
||||||
{
|
|
||||||
JSON retVal;
|
|
||||||
|
|
||||||
retVal["id"] = (int64_t)id;
|
|
||||||
retVal["name"] = name;
|
|
||||||
retVal["shortName"] = shortName;
|
|
||||||
retVal["packedAddress"] = std::to_string((long long)this);
|
|
||||||
|
|
||||||
retVal["dimSize"] = dimSize;
|
|
||||||
retVal["typeSize"] = typeSize;
|
|
||||||
retVal["state"] = (int)isNonDistribute;
|
|
||||||
retVal["location"] = (int)locationPos.first;
|
|
||||||
retVal["locName"] = locationPos.second;
|
|
||||||
|
|
||||||
retVal["isTemplFlag"] = (int)isTemplFlag;
|
|
||||||
retVal["isLoopArrayFlag"] = (int)isLoopArrayFlag;
|
|
||||||
|
|
||||||
JSON deprToDist = nlohmann::json::array();
|
|
||||||
for (int i = 0; i < deprecateToDistribute.size(); ++i)
|
|
||||||
deprToDist.push_back((int)deprecateToDistribute[i]);
|
|
||||||
retVal["deprecateToDist"] = deprToDist;
|
|
||||||
|
|
||||||
JSON mappedDimsJ = nlohmann::json::array();
|
|
||||||
for (int i = 0; i < mappedDims.size(); ++i)
|
|
||||||
mappedDimsJ.push_back((int)mappedDims[i]);
|
|
||||||
retVal["mappedDims"] = mappedDimsJ;
|
|
||||||
|
|
||||||
JSON sizesJ = nlohmann::json::array();
|
|
||||||
for (int i = 0; i < sizes.size(); ++i)
|
|
||||||
{
|
|
||||||
JSON pair;
|
|
||||||
pair["key"] = sizes[i].first;
|
|
||||||
pair["value"] = sizes[i].second;
|
|
||||||
sizesJ.push_back(pair);
|
|
||||||
}
|
|
||||||
retVal["sizes"] = sizesJ;
|
|
||||||
|
|
||||||
JSON regions = nlohmann::json::array();
|
|
||||||
for (auto& reg : containsInRegions)
|
|
||||||
regions.push_back(reg);
|
|
||||||
retVal["regions"] = regions;
|
|
||||||
|
|
||||||
|
|
||||||
JSON declPlacesJ = nlohmann::json::array();
|
|
||||||
for (auto& place : declPlaces)
|
|
||||||
{
|
|
||||||
JSON elem;
|
|
||||||
elem["file"] = place.first;
|
|
||||||
elem["line"] = place.second;
|
|
||||||
|
|
||||||
declPlacesJ.push_back(elem);
|
|
||||||
}
|
|
||||||
retVal["declPlaces"] = declPlacesJ;
|
|
||||||
|
|
||||||
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 ®Name) { 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;
|
|
||||||
deprecateToDistribute[dim] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeprecateAllDims()
|
|
||||||
{
|
|
||||||
for (int dim = 0; dim < dimSize; ++dim)
|
|
||||||
deprecateToDistribute[dim] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsDimDepracated(const int dim) const
|
|
||||||
{
|
|
||||||
if (dim >= dimSize)
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (templateDimsOrder.size() == 0)
|
|
||||||
return deprecateToDistribute[dim];
|
|
||||||
else
|
|
||||||
return deprecateToDistribute[templateDimsOrder[dim]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsAllDeprecated() const
|
|
||||||
{
|
|
||||||
bool ret = true;
|
|
||||||
for (int z = 0; z < dimSize; ++z)
|
|
||||||
ret = ret && deprecateToDistribute[z];
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const VECTOR<bool>& GetDeprecetedDims() const { return deprecateToDistribute; }
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -1,766 +0,0 @@
|
|||||||
#include "Array.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "graph_calls.h"
|
|
||||||
#include "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 (deprecatedByIO.find(symb->identifier()) != deprecatedByIO.end())
|
|
||||||
itNew->second.first->SetDistributeFlag(DIST::IO_PRIV);
|
|
||||||
else if (isArrayInModule || privates.find(symb->identifier()) != privates.end())
|
|
||||||
{
|
|
||||||
//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 (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;
|
|
||||||
}
|
|
||||||
@@ -1,292 +0,0 @@
|
|||||||
#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 ©)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
@@ -1,648 +0,0 @@
|
|||||||
#include "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 "errors.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "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;
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "graph_loops.h"
|
|
||||||
#include "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);
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
#include "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> ¶mArc, 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> ¶mArc, 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>;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "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> ¶mArc, const unsigned info);
|
|
||||||
void AddArc(const vType V1, const vType V2, const std::pair<wType, attrType> ¶mArc, 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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,615 +0,0 @@
|
|||||||
#include "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.h"
|
|
||||||
#include "errors.h"
|
|
||||||
#include "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)
|
|
||||||
sendMessage_2lvl(4, k, (int)AllCycles.size());
|
|
||||||
|
|
||||||
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(2);
|
|
||||||
|
|
||||||
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];
|
|
||||||
sendMessage_2lvl(5, z, (int)arrays.size());
|
|
||||||
|
|
||||||
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(2);
|
|
||||||
}
|
|
||||||
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
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#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
@@ -1,184 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "Array.h"
|
|
||||||
#include "DvmhDirectiveBase.h"
|
|
||||||
#include "AstWrapper.h"
|
|
||||||
#include "types.h"
|
|
||||||
#include "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 ©From) : 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);
|
|
||||||
@@ -1,819 +0,0 @@
|
|||||||
#include "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 "errors.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "json.hpp"
|
|
||||||
|
|
||||||
#include "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;
|
|
||||||
|
|
||||||
using nlohmann::json;
|
|
||||||
|
|
||||||
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>>> ¶llelOnRule)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
json AlignRuleBase::toJson()
|
|
||||||
{
|
|
||||||
json retVal;
|
|
||||||
|
|
||||||
retVal["packedAlignArrayAddress"] = alignArray ? std::to_string((long long)alignArray) : std::to_string((long long)-1);
|
|
||||||
retVal["packedAlignWithAddress"] = alignWith ? std::to_string((long long)alignWith) : std::to_string((long long)-1);
|
|
||||||
|
|
||||||
json alignRules = json::array();
|
|
||||||
for (auto& rule : alignRule)
|
|
||||||
{
|
|
||||||
json pair;
|
|
||||||
pair["key"] = rule.first;
|
|
||||||
pair["value"] = rule.second;
|
|
||||||
alignRules.push_back(pair);
|
|
||||||
}
|
|
||||||
retVal["alignRule"] = alignRules;
|
|
||||||
|
|
||||||
json alignRuleWithJ = json::array();
|
|
||||||
for (auto& [dimNum, AB] : alignRuleWith)
|
|
||||||
{
|
|
||||||
json tuple;
|
|
||||||
tuple["dimNum"] = dimNum;
|
|
||||||
tuple["a"] = AB.first;
|
|
||||||
tuple["b"] = AB.second;
|
|
||||||
|
|
||||||
alignRuleWithJ.push_back(tuple);
|
|
||||||
}
|
|
||||||
retVal["alignRuleWith"] = alignRuleWithJ;
|
|
||||||
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" };
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "json.hpp"
|
|
||||||
|
|
||||||
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;
|
|
||||||
nlohmann::json toJson();
|
|
||||||
|
|
||||||
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);
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <set>
|
|
||||||
#include "dvm.h"
|
|
||||||
#include "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
@@ -1,171 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
#include "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);
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "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
@@ -1,120 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "graph_calls_func.h"
|
|
||||||
#include "graph_loops_func.h"
|
|
||||||
#include "expr_transform.h"
|
|
||||||
#include "../ParallelizationRegions/ParRegions.h"
|
|
||||||
#include "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);
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "graph_loops_func.h"
|
|
||||||
#include "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);
|
|
||||||
};
|
|
||||||
@@ -1,341 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "dvm.h"
|
|
||||||
#include "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*>>&);
|
|
||||||
};
|
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "DvmhRegions/DvmhRegionInserter.h"
|
|
||||||
|
|
||||||
class RegionsMerger
|
|
||||||
{
|
|
||||||
std::vector<DvmhRegion*> ®ions;
|
|
||||||
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();
|
|
||||||
};
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#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();
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "dvm.h"
|
|
||||||
#include "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);
|
|
||||||
};
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
#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; }
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#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;
|
|
||||||
};
|
|
||||||
@@ -1,357 +0,0 @@
|
|||||||
#include "dvm.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "./createParallelRegions.h"
|
|
||||||
|
|
||||||
#include "../CreateInterTree/CreateInterTree.h"
|
|
||||||
#include "graph_calls.h"
|
|
||||||
#include "./gcov_info.h"
|
|
||||||
#include "./gCov_parser_func.h"
|
|
||||||
#include "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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#include "./gcov_info.h"
|
|
||||||
#include "../CreateInterTree/CreateInterTree.h"
|
|
||||||
#include "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);
|
|
||||||
@@ -1,473 +0,0 @@
|
|||||||
#include "leak_detector.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "dvm.h"
|
|
||||||
#include "gCov_parser_func.h"
|
|
||||||
#include "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());
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "dvm.h"
|
|
||||||
#include "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);
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
#include "leak_detector.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <map>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "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; }
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "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
@@ -1,315 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#include "AstWrapper.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "../DirectiveProcessing/shadow.h"
|
|
||||||
#include "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);
|
|
||||||
@@ -1,954 +0,0 @@
|
|||||||
#include "leak_detector.h"
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "errors.h"
|
|
||||||
#include "graph_calls.h"
|
|
||||||
#include "../Distribution/Distribution.h"
|
|
||||||
#include "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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#include "graph_calls.h"
|
|
||||||
#include "graph_loops.h"
|
|
||||||
#include "../ParallelizationRegions/ParRegions.h"
|
|
||||||
#include "Utils/json.hpp"
|
|
||||||
|
|
||||||
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);
|
|
||||||
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*> ®ions);
|
|
||||||
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);
|
|
||||||
nlohmann::json convertToJson(const std::map<std::string, std::vector<FuncInfo*>>& funcsByFile);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,546 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#include "errors.h"
|
|
||||||
#include "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);
|
|
||||||
|
|
||||||
enum class LoopType { NONE, FOR, WHILE, IMPLICIT };
|
|
||||||
|
|
||||||
struct InductiveVariables
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::string mainVar;
|
|
||||||
std::set<std::string> allVars;
|
|
||||||
|
|
||||||
public:
|
|
||||||
InductiveVariables() { }
|
|
||||||
|
|
||||||
explicit InductiveVariables(const std::string& mainVar, const std::set<std::string>& allVars) : mainVar(mainVar), allVars(allVars) { };
|
|
||||||
|
|
||||||
std::string getMainVar() const { return mainVar; }
|
|
||||||
std::set<std::string> getAllVars() const { return allVars; }
|
|
||||||
|
|
||||||
void addVar(const std::string& var) { allVars.insert(var); }
|
|
||||||
void addMainVar(const std::string& var) { mainVar = var; allVars.insert(var); }
|
|
||||||
|
|
||||||
void replaceMainVar(const std::string& var)
|
|
||||||
{
|
|
||||||
allVars.erase(mainVar);
|
|
||||||
|
|
||||||
addMainVar(var);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
loopType = LoopType::NONE;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (messages == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
bool isFor() const { return loopType == LoopType::FOR; }
|
|
||||||
|
|
||||||
bool isWhile() const { return loopType == LoopType::WHILE; }
|
|
||||||
|
|
||||||
bool isImplicit() const { return loopType == LoopType::IMPLICIT; }
|
|
||||||
|
|
||||||
std::string loopSymbol() const { return loopSymbols.getMainVar(); }
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
InductiveVariables loopSymbols;
|
|
||||||
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;
|
|
||||||
|
|
||||||
LoopType loopType;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user