moved
This commit is contained in:
524
Sapfor/CMakeLists.txt
Normal file
524
Sapfor/CMakeLists.txt
Normal file
@@ -0,0 +1,524 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set(project Sapfor)
|
||||
if (TARGET ${project})
|
||||
return()
|
||||
endif ()
|
||||
project(${project})
|
||||
message("processing ${project}")
|
||||
#include(CTest)
|
||||
|
||||
add_definitions("-D SYS5")
|
||||
add_definitions("-D YYDEBUG")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
set(fdvm_include ../../../dvm/fdvm/trunk/include)
|
||||
set(sage_include_1 ../../../dvm/fdvm/trunk/Sage/lib/include)
|
||||
set(sage_include_2 ../../../dvm/fdvm/trunk/Sage/h/)
|
||||
set(libdb_sources ../../../dvm/fdvm/trunk/Sage/lib/oldsrc)
|
||||
set(sage_sources ../../../dvm/fdvm/trunk/Sage/lib/newsrc)
|
||||
set(sagepp_sources ../../../dvm/fdvm/trunk/Sage/Sage++)
|
||||
set(parser_sources ../../../dvm/fdvm/trunk/parser)
|
||||
set(pppa_sources ../../../dvm/tools/pppa/trunk/src)
|
||||
set(zlib_sources ../../../dvm/tools/Zlib)
|
||||
|
||||
# Read pathes to external sapfor directories
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/paths.txt")
|
||||
message("Found paths.txt, using custom paths.")
|
||||
FILE(STRINGS ./paths.txt SAPFOR_PATHS)
|
||||
else ()
|
||||
message("Not found paths.txt, using default paths.")
|
||||
FILE(STRINGS ./paths.default.txt SAPFOR_PATHS)
|
||||
endif ()
|
||||
|
||||
foreach (NameAndValue ${SAPFOR_PATHS})
|
||||
# Strip leading spaces
|
||||
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
|
||||
# Find variable name
|
||||
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
|
||||
# Find the value
|
||||
string(REPLACE "${Name}=" "" Value ${NameAndValue})
|
||||
# Set the variable, note the ../ because we are deeper than the file
|
||||
set(${Name} "${Value}")
|
||||
message("Using ${Name} ${${Name}}")
|
||||
endforeach ()
|
||||
|
||||
include_directories(_src)
|
||||
#Sage lib includes
|
||||
include_directories(${fdvm_include})
|
||||
include_directories(${sage_include_1})
|
||||
include_directories(${sage_include_2})
|
||||
#Zlib includes
|
||||
include_directories(${zlib_sources}/include)
|
||||
#PPPA includes
|
||||
include_directories(${pppa_sources})
|
||||
|
||||
set(PR_PARAM _src/ProjectParameters/projectParameters.cpp
|
||||
_src/ProjectParameters/projectParameters.h)
|
||||
|
||||
set(GR_LAYOUT _src/VisualizerCalls/graphLayout/algebra.cpp
|
||||
_src/VisualizerCalls/graphLayout/algebra.hpp
|
||||
_src/VisualizerCalls/graphLayout/fruchterman_reingold.cpp
|
||||
_src/VisualizerCalls/graphLayout/fruchterman_reingold.hpp
|
||||
_src/VisualizerCalls/graphLayout/kamada_kawai.cpp
|
||||
_src/VisualizerCalls/graphLayout/kamada_kawai.hpp
|
||||
_src/VisualizerCalls/graphLayout/layout.cpp
|
||||
_src/VisualizerCalls/graphLayout/layout.hpp
|
||||
_src/VisualizerCalls/graphLayout/nodesoup.cpp
|
||||
_src/VisualizerCalls/graphLayout/nodesoup.hpp)
|
||||
|
||||
set(VS_CALLS _src/VisualizerCalls/get_information.cpp
|
||||
_src/VisualizerCalls/get_information.h
|
||||
_src/VisualizerCalls/SendMessage.cpp
|
||||
_src/VisualizerCalls/SendMessage.h
|
||||
_src/VisualizerCalls/BuildGraph.cpp
|
||||
_src/VisualizerCalls/BuildGraph.h)
|
||||
|
||||
set(VERIF _src/VerificationCode/CorrectVarDecl.cpp
|
||||
_src/VerificationCode/IncludeChecker.cpp
|
||||
_src/VerificationCode/StructureChecker.cpp
|
||||
_src/VerificationCode/VerifySageStructures.cpp
|
||||
_src/VerificationCode/verifications.h)
|
||||
|
||||
set(UTILS _src/Utils/AstWrapper.h
|
||||
_src/Utils/BoostStackTrace.cpp
|
||||
_src/Utils/CommonBlock.h
|
||||
_src/Utils/DefUseList.h
|
||||
_src/Utils/errors.h
|
||||
_src/Utils/leak_detector.h
|
||||
_src/Utils/RationalNum.cpp
|
||||
_src/Utils/RationalNum.h
|
||||
_src/Utils/SgUtils.cpp
|
||||
_src/Utils/SgUtils.h
|
||||
_src/Utils/types.h
|
||||
_src/Utils/utils.cpp
|
||||
_src/Utils/utils.h
|
||||
_src/Utils/version.h
|
||||
_src/Utils/module_utils.h
|
||||
_src/Utils/module_utils.cpp)
|
||||
|
||||
set(OMEGA _src/SageAnalysisTool/OmegaForSage/add-assert.cpp
|
||||
_src/SageAnalysisTool/OmegaForSage/affine.cpp
|
||||
_src/SageAnalysisTool/OmegaForSage/cover.cpp
|
||||
_src/SageAnalysisTool/OmegaForSage/ddomega-build.cpp
|
||||
_src/SageAnalysisTool/OmegaForSage/ddomega-use.cpp
|
||||
_src/SageAnalysisTool/OmegaForSage/ddomega.cpp
|
||||
_src/SageAnalysisTool/OmegaForSage/debug.cpp
|
||||
_src/SageAnalysisTool/OmegaForSage/ip.cpp
|
||||
_src/SageAnalysisTool/OmegaForSage/kill.cpp
|
||||
_src/SageAnalysisTool/OmegaForSage/refine.cpp
|
||||
_src/SageAnalysisTool/OmegaForSage/sagedriver.cpp
|
||||
_src/SageAnalysisTool/annotationDriver.cpp
|
||||
_src/SageAnalysisTool/arrayRef.cpp
|
||||
_src/SageAnalysisTool/computeInducVar.cpp
|
||||
_src/SageAnalysisTool/constanteProp.cpp
|
||||
_src/SageAnalysisTool/constanteSet.h
|
||||
_src/SageAnalysisTool/controlFlow.cpp
|
||||
_src/SageAnalysisTool/defUse.cpp
|
||||
_src/SageAnalysisTool/dependence.cpp
|
||||
_src/SageAnalysisTool/depGraph.cpp
|
||||
_src/SageAnalysisTool/depInterface.cpp
|
||||
_src/SageAnalysisTool/depInterfaceExt.h
|
||||
_src/SageAnalysisTool/flowAnalysis.cpp
|
||||
_src/SageAnalysisTool/inducVar.h
|
||||
_src/SageAnalysisTool/intrinsic.cpp
|
||||
_src/SageAnalysisTool/invariant.cpp
|
||||
_src/SageAnalysisTool/loopTransform.cpp
|
||||
_src/SageAnalysisTool/set.cpp)
|
||||
|
||||
set(PRIV _src/PrivateAnalyzer/private_analyzer.cpp
|
||||
_src/PrivateAnalyzer/private_analyzer.h)
|
||||
|
||||
set(FDVM ${fdvm_sources}/acc.cpp
|
||||
${fdvm_sources}/acc_across.cpp
|
||||
${fdvm_sources}/acc_across_analyzer.cpp
|
||||
${fdvm_sources}/acc_analyzer.cpp
|
||||
${fdvm_sources}/acc_data.cpp
|
||||
${fdvm_sources}/acc_f2c.cpp
|
||||
${fdvm_sources}/acc_f2c_handlers.cpp
|
||||
${fdvm_sources}/acc_rtc.cpp
|
||||
${fdvm_sources}/acc_rtc.cpp
|
||||
${fdvm_sources}/acc_utilities.cpp
|
||||
${fdvm_sources}/aks_analyzeLoops.cpp
|
||||
${fdvm_sources}/aks_structs.cpp
|
||||
${fdvm_sources}/checkpoint.cpp
|
||||
${fdvm_sources}/debug.cpp
|
||||
${fdvm_sources}/dvm.cpp
|
||||
${fdvm_sources}/calls.cpp
|
||||
${fdvm_sources}/funcall.cpp
|
||||
${fdvm_sources}/help.cpp
|
||||
${fdvm_sources}/hpf.cpp
|
||||
${fdvm_sources}/io.cpp
|
||||
${fdvm_sources}/omp.cpp
|
||||
${fdvm_sources}/ompdebug.cpp
|
||||
${fdvm_sources}/parloop.cpp
|
||||
${fdvm_sources}/stmt.cpp)
|
||||
|
||||
set(PARALLEL_REG _src/ParallelizationRegions/ParRegions.cpp
|
||||
_src/ParallelizationRegions/ParRegions.h
|
||||
_src/ParallelizationRegions/ParRegions_func.h
|
||||
_src/ParallelizationRegions/expand_extract_reg.cpp
|
||||
_src/ParallelizationRegions/expand_extract_reg.h
|
||||
_src/ParallelizationRegions/resolve_par_reg_conflicts.cpp
|
||||
_src/ParallelizationRegions/resolve_par_reg_conflicts.h)
|
||||
|
||||
set(TR_DEAD_CODE _src/Transformations/dead_code.cpp
|
||||
_src/Transformations/dead_code.h)
|
||||
set(TR_CP _src/Transformations/checkpoints.cpp
|
||||
_src/Transformations/checkpoints.h)
|
||||
set(TR_VECTOR _src/Transformations/array_assign_to_loop.cpp
|
||||
_src/Transformations/array_assign_to_loop.h)
|
||||
set(TR_ENDDO_LOOP _src/Transformations/enddo_loop_converter.cpp
|
||||
_src/Transformations/enddo_loop_converter.h)
|
||||
set(TR_LOOP_NEST _src/Transformations/loop_transform.cpp
|
||||
_src/Transformations/loop_transform.h)
|
||||
set(TR_LOOP_COMB _src/Transformations/loops_combiner.cpp
|
||||
_src/Transformations/loops_combiner.h)
|
||||
set(TR_LOOP_SPLIT _src/Transformations/loops_splitter.cpp
|
||||
_src/Transformations/loops_splitter.h)
|
||||
set(TR_LOOP_UNROLL _src/Transformations/loops_unrolling.cpp
|
||||
_src/Transformations/loops_unrolling.h)
|
||||
set(TR_PRIV_BR _src/Transformations/private_arrays_resizing.cpp
|
||||
_src/Transformations/private_arrays_resizing.h)
|
||||
set(TR_PRIV_DEL _src/Transformations/private_removing.cpp
|
||||
_src/Transformations/private_removing.h)
|
||||
set(TR_SWAP_ARR_DIMS _src/Transformations/swap_array_dims.cpp
|
||||
_src/Transformations/swap_array_dims.h)
|
||||
set(TR_FUNC_DUP _src/Transformations/uniq_call_chain_dup.cpp
|
||||
_src/Transformations/uniq_call_chain_dup.h)
|
||||
set(TR_FUNC_PURE _src/Transformations/function_purifying.cpp
|
||||
_src/Transformations/function_purifying.h)
|
||||
set(TR_GV _src/Transformations/fix_common_blocks.cpp
|
||||
_src/Transformations/fix_common_blocks.h)
|
||||
set(TR_CONV _src/Transformations/convert_to_c.cpp
|
||||
_src/Transformations/convert_to_c.h)
|
||||
set(TR_IMPLICIT_NONE _src/Transformations/set_implicit_none.cpp
|
||||
_src/Transformations/set_implicit_none.h)
|
||||
set(TR_REPLACE_ARRAYS_IN_IO _src/Transformations/replace_dist_arrays_in_io.cpp
|
||||
_src/Transformations/replace_dist_arrays_in_io.h)
|
||||
|
||||
set(TRANSFORMS
|
||||
${TR_DEAD_CODE}
|
||||
${TR_CP}
|
||||
${TR_VECTOR}
|
||||
${TR_ENDDO_LOOP}
|
||||
${TR_LOOP_NEST}
|
||||
${TR_LOOP_COMB}
|
||||
${TR_LOOP_SPLIT}
|
||||
${TR_PRIV_BR}
|
||||
${TR_SWAP_ARR_DIMS}
|
||||
${TR_FUNC_DUP}
|
||||
${TR_FUNC_PURE}
|
||||
${TR_LOOP_UNROLL}
|
||||
${TR_GV}
|
||||
${TR_PRIV_DEL}
|
||||
${TR_CONV}
|
||||
${TR_PRIV_DEL}
|
||||
${TR_IMPLICIT_NONE}
|
||||
${TR_REPLACE_ARRAYS_IN_IO})
|
||||
|
||||
set(CFG _src/CFGraph/IR.cpp
|
||||
_src/CFGraph/IR.h
|
||||
_src/CFGraph/CFGraph.cpp
|
||||
_src/CFGraph/CFGraph.h
|
||||
_src/CFGraph/RD_subst.cpp
|
||||
_src/CFGraph/RD_subst.h
|
||||
_src/CFGraph/live_variable_analysis.cpp
|
||||
_src/CFGraph/live_variable_analysis.h
|
||||
_src/CFGraph/private_variables_analysis.cpp
|
||||
_src/CFGraph/private_variables_analysis.h
|
||||
_src/CFGraph/IRSSAForm.cpp
|
||||
_src/CFGraph/IRSSAForm.h
|
||||
)
|
||||
|
||||
set(DATA_FLOW
|
||||
_src/CFGraph/DataFlow/data_flow.h
|
||||
_src/CFGraph/DataFlow/data_flow_impl.h
|
||||
_src/CFGraph/DataFlow/backward_data_flow.h
|
||||
_src/CFGraph/DataFlow/backward_data_flow_impl.h
|
||||
)
|
||||
|
||||
set(CREATE_INTER_T _src/CreateInterTree/CreateInterTree.cpp
|
||||
_src/CreateInterTree/CreateInterTree.h)
|
||||
|
||||
set(DIRA _src/DirectiveProcessing/directive_analyzer.cpp
|
||||
_src/DirectiveProcessing/directive_analyzer.h
|
||||
_src/DirectiveProcessing/directive_creator.cpp
|
||||
_src/DirectiveProcessing/directive_creator_base.cpp
|
||||
_src/DirectiveProcessing/directive_creator.h
|
||||
_src/DirectiveProcessing/directive_parser.cpp
|
||||
_src/DirectiveProcessing/directive_parser.h
|
||||
_src/DirectiveProcessing/directive_omp_parser.cpp
|
||||
_src/DirectiveProcessing/directive_omp_parser.h
|
||||
_src/DirectiveProcessing/insert_directive.cpp
|
||||
_src/DirectiveProcessing/insert_directive.h
|
||||
_src/DirectiveProcessing/remote_access.cpp
|
||||
_src/DirectiveProcessing/remote_access_base.cpp
|
||||
_src/DirectiveProcessing/remote_access.h
|
||||
_src/DirectiveProcessing/shadow.cpp
|
||||
_src/DirectiveProcessing/shadow.h
|
||||
_src/DirectiveProcessing/spf_directive_preproc.cpp)
|
||||
|
||||
set(DISTR _src/Distribution/Array.cpp
|
||||
_src/Distribution/ArrayAnalysis.cpp
|
||||
_src/Distribution/Array.h
|
||||
_src/Distribution/Arrays.h
|
||||
_src/Distribution/CreateDistributionDirs.cpp
|
||||
_src/Distribution/CreateDistributionDirs.h
|
||||
_src/Distribution/Cycle.cpp
|
||||
_src/Distribution/Cycle.h
|
||||
_src/Distribution/Distribution.cpp
|
||||
_src/Distribution/Distribution.h
|
||||
_src/Distribution/DvmhDirective.cpp
|
||||
_src/Distribution/DvmhDirective.h
|
||||
_src/Distribution/DvmhDirective_func.h
|
||||
_src/Distribution/DvmhDirectiveBase.cpp
|
||||
_src/Distribution/DvmhDirectiveBase.h
|
||||
_src/Distribution/GraphCSR.cpp
|
||||
_src/Distribution/GraphCSR.h)
|
||||
|
||||
set(DVMH_REG _src/DvmhRegions/DvmhRegionInserter.cpp
|
||||
_src/DvmhRegions/DvmhRegionInserter.h
|
||||
_src/DvmhRegions/RegionsMerger.cpp
|
||||
_src/DvmhRegions/RegionsMerger.h
|
||||
_src/DvmhRegions/ReadWriteAnalyzer.cpp
|
||||
_src/DvmhRegions/ReadWriteAnalyzer.h
|
||||
_src/DvmhRegions/LoopChecker.cpp
|
||||
_src/DvmhRegions/LoopChecker.h
|
||||
_src/DvmhRegions/DvmhRegion.cpp
|
||||
_src/DvmhRegions/DvmhRegion.h
|
||||
_src/DvmhRegions/VarUsages.cpp
|
||||
_src/DvmhRegions/VarUsages.h
|
||||
_src/DvmhRegions/TypedSymbol.cpp
|
||||
_src/DvmhRegions/TypedSymbol.h)
|
||||
|
||||
set(DYNA _src/DynamicAnalysis/createParallelRegions.cpp
|
||||
_src/DynamicAnalysis/createParallelRegions.h
|
||||
_src/DynamicAnalysis/gcov_info.cpp
|
||||
_src/DynamicAnalysis/gcov_info.h
|
||||
_src/DynamicAnalysis/gCov_parser.cpp
|
||||
_src/DynamicAnalysis/gCov_parser_func.h)
|
||||
|
||||
set(EXPR_TRANSFORM _src/ExpressionTransform/control_flow_graph_part.cpp
|
||||
_src/ExpressionTransform/expr_transform.cpp
|
||||
_src/ExpressionTransform/expr_transform.h)
|
||||
|
||||
set(GR_CALL _src/GraphCall/graph_calls.cpp
|
||||
_src/GraphCall/graph_calls.h
|
||||
_src/GraphCall/graph_calls_base.cpp
|
||||
_src/GraphCall/graph_calls_func.h)
|
||||
|
||||
set(GR_LOOP _src/GraphLoop/graph_loops_base.cpp
|
||||
_src/GraphLoop/graph_loops.cpp
|
||||
_src/GraphLoop/graph_loops.h
|
||||
_src/GraphLoop/graph_loops_func.h)
|
||||
|
||||
set(INLINER _src/Inliner/inliner.cpp
|
||||
_src/Inliner/inliner.h)
|
||||
|
||||
set(LOOP_ANALYZER _src/LoopAnalyzer/allocations_prepoc.cpp
|
||||
_src/LoopAnalyzer/dep_analyzer.cpp
|
||||
_src/LoopAnalyzer/loop_analyzer.cpp
|
||||
_src/LoopAnalyzer/loop_analyzer.h)
|
||||
|
||||
set(RENAME_SYMBOLS _src/RenameSymbols/rename_symbols.cpp
|
||||
_src/RenameSymbols/rename_symbols.h)
|
||||
|
||||
|
||||
set(MAIN _src/Sapfor.cpp
|
||||
_src/Sapfor.h
|
||||
_src/SapforData.h
|
||||
_src/Utils/PassManager.h)
|
||||
|
||||
set(PREDICTOR _src/Predictor/PredictScheme.cpp
|
||||
_src/Predictor/PredictScheme.h)
|
||||
|
||||
set(PROJ_MAN _src/ProjectManipulation/ParseFiles.cpp
|
||||
_src/ProjectManipulation/ParseFiles.h
|
||||
_src/ProjectManipulation/StdCapture.h
|
||||
_src/ProjectManipulation/PerfAnalyzer.cpp
|
||||
_src/ProjectManipulation/PerfAnalyzer.h
|
||||
_src/ProjectManipulation/FileInfo.cpp
|
||||
_src/ProjectManipulation/FileInfo.h
|
||||
_src/ProjectManipulation/ConvertFiles.cpp
|
||||
_src/ProjectManipulation/ConvertFiles.h)
|
||||
|
||||
set(PARSER ${parser_sources}/cftn.c
|
||||
${parser_sources}/errors.c
|
||||
${parser_sources}/gram1.tab.c
|
||||
${parser_sources}/hash.c
|
||||
${parser_sources}/init.c
|
||||
${parser_sources}/lexfdvm.c
|
||||
${parser_sources}/lists.c
|
||||
${parser_sources}/low_hpf.c
|
||||
${parser_sources}/misc.c
|
||||
${parser_sources}/stat.c
|
||||
${parser_sources}/sym.c
|
||||
${parser_sources}/types.c
|
||||
${parser_sources}/unparse_hpf.c)
|
||||
|
||||
set(PPPA ${pppa_sources}/inter.cpp
|
||||
${pppa_sources}/potensyn.cpp
|
||||
${pppa_sources}/stat.cpp
|
||||
${pppa_sources}/statfile.cpp
|
||||
${pppa_sources}/statinter.cpp
|
||||
${pppa_sources}/statlist.cpp
|
||||
${pppa_sources}/statprintf.cpp
|
||||
${pppa_sources}/statread.cpp
|
||||
${pppa_sources}/treeinter.cpp
|
||||
|
||||
${pppa_sources}/bool.h
|
||||
${pppa_sources}/dvmh_stat.h
|
||||
${pppa_sources}/inter.h
|
||||
${pppa_sources}/potensyn.h
|
||||
${pppa_sources}/statist.h
|
||||
${pppa_sources}/statlist.h
|
||||
${pppa_sources}/statprintf.h
|
||||
${pppa_sources}/statread.h
|
||||
${pppa_sources}/strall.h
|
||||
${pppa_sources}/sysstat.h
|
||||
${pppa_sources}/treeinter.h
|
||||
${pppa_sources}/ver.h
|
||||
${pppa_sources}/statinter.h
|
||||
${pppa_sources}/json.hpp)
|
||||
|
||||
set(ZLIB ${zlib_sources}/src/adler32.c
|
||||
${zlib_sources}/src/compress.c
|
||||
${zlib_sources}/src/crc32.c
|
||||
${zlib_sources}/src/deflate.c
|
||||
${zlib_sources}/src/gzio.c
|
||||
${zlib_sources}/src/infblock.c
|
||||
${zlib_sources}/src/infcodes.c
|
||||
${zlib_sources}/src/inffast.c
|
||||
${zlib_sources}/src/inflate.c
|
||||
${zlib_sources}/src/inftrees.c
|
||||
${zlib_sources}/src/infutil.c
|
||||
${zlib_sources}/src/trees.c
|
||||
${zlib_sources}/src/uncompr.c
|
||||
${zlib_sources}/src/zutil.c)
|
||||
|
||||
set(SOURCE_EXE
|
||||
${CFG}
|
||||
${DATA_FLOW}
|
||||
${CREATE_INTER_T}
|
||||
${DIRA}
|
||||
${DISTR}
|
||||
${DVMH_REG}
|
||||
${DYNA}
|
||||
${EXPR_TRANSFORM}
|
||||
${GR_CALL}
|
||||
${GR_LOOP}
|
||||
${INLINER}
|
||||
${LOOP_ANALYZER}
|
||||
${RENAME_SYMBOLS}
|
||||
${TRANSFORMS}
|
||||
${PARALLEL_REG}
|
||||
${PRIV}
|
||||
${FDVM}
|
||||
${OMEGA}
|
||||
${UTILS}
|
||||
${VERIF}
|
||||
${VS_CALLS}
|
||||
${MAIN}
|
||||
${PREDICTOR}
|
||||
${PARSER}
|
||||
${PPPA}
|
||||
${ZLIB}
|
||||
${GR_LAYOUT}
|
||||
${PR_PARAM}
|
||||
${PROJ_MAN})
|
||||
|
||||
add_executable(Sapfor_F ${SOURCE_EXE})
|
||||
source_group (CFGraph FILES ${CFG})
|
||||
source_group (CFGraph\\DataFlow FILES ${DATA_FLOW})
|
||||
|
||||
source_group (Transformations\\DeadCodeRemoving FILES ${TR_DEAD_CODE})
|
||||
source_group (Transformations\\ExpressionSubstitution FILES ${EXPR_TRANSFORM})
|
||||
source_group (Transformations\\CheckPoints FILES ${TR_CP})
|
||||
source_group (Transformations\\LoopEndDoConverter FILES ${TR_ENDDO_LOOP})
|
||||
source_group (Transformations\\LoopNesting FILES ${TR_LOOP_NEST})
|
||||
source_group (Transformations\\LoopCombining FILES ${TR_LOOP_COMB})
|
||||
source_group (Transformations\\LoopSplitting FILES ${TR_LOOP_SPLIT})
|
||||
source_group (Transformations\\LoopUnrolling FILES ${TR_LOOP_UNROLL})
|
||||
source_group (Transformations\\FunctionDuplication FILES ${TR_FUNC_DUP})
|
||||
source_group (Transformations\\FunctionInlining FILES ${INLINER})
|
||||
source_group (Transformations\\FunctionPurifying FILES ${TR_FUNC_PURE})
|
||||
source_group (Transformations\\ArrayDimsSwapping FILES ${TR_SWAP_ARR_DIMS})
|
||||
source_group (Transformations\\PrivateArrayResizing FILES ${TR_PRIV_BR})
|
||||
source_group (Transformations\\PrivateArrayRemoving FILES ${TR_PRIV_DEL})
|
||||
source_group (Transformations\\VectorAssignToLoop FILES ${TR_VECTOR})
|
||||
source_group (Transformations\\RenameSymbols FILES ${RENAME_SYMBOLS})
|
||||
source_group (Transformations\\GlobalVariables FILES ${TR_GV})
|
||||
source_group (Transformations\\ConvertToC FILES ${TR_CONV})
|
||||
source_group (Transformations\\SetImplicitNone FILES ${TR_IMPLICIT_NONE})
|
||||
source_group (Transformations\\ReplaceArraysInIO FILES ${TR_REPLACE_ARRAYS_IN_IO})
|
||||
|
||||
|
||||
source_group (CreateIntervals FILES ${CREATE_INTER_T})
|
||||
source_group (DirectiveProcessing FILES ${DIRA})
|
||||
source_group (Distribution FILES ${DISTR})
|
||||
source_group (DvmhRegions FILES ${DVMH_REG})
|
||||
source_group (DynamicAnalysis FILES ${DYNA})
|
||||
source_group (GraphCall FILES ${GR_CALL})
|
||||
source_group (GraphLoop FILES ${GR_LOOP})
|
||||
source_group (LoopAnalyzer FILES ${LOOP_ANALYZER})
|
||||
source_group (ParallelizationRegions FILES ${PARALLEL_REG})
|
||||
source_group (PrivateAnalyzer FILES ${PRIV})
|
||||
source_group (FDVM_Compiler FILES ${FDVM})
|
||||
source_group (SageExtension FILES ${OMEGA})
|
||||
source_group (Utils FILES ${UTILS})
|
||||
source_group (VerificationCode FILES ${VERIF})
|
||||
source_group (ProjectParameters FILES ${PR_PARAM})
|
||||
source_group (ProjectManipulation FILES ${PROJ_MAN})
|
||||
|
||||
source_group (VisualizerCalls FILES ${VS_CALLS})
|
||||
source_group (VisualizerCalls\\GraphLayout FILES ${GR_LAYOUT})
|
||||
|
||||
source_group (_SapforMain FILES ${MAIN})
|
||||
source_group (Predictor FILES ${PREDICTOR})
|
||||
source_group (Parser FILES ${PARSER})
|
||||
source_group (PPPA\\PPPA FILES ${PPPA})
|
||||
source_group (PPPA\\ZLib FILES ${ZLIB})
|
||||
|
||||
if (MSVC_IDE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /Zc:__cplusplus")
|
||||
else()
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
|
||||
endif()
|
||||
|
||||
add_subdirectory(FDVM)
|
||||
|
||||
add_definitions("-D __SPF")
|
||||
add_definitions("-D _CRT_SECURE_NO_WARNINGS")
|
||||
add_definitions("-D _CRT_NON_CONFORMING_SWPRINTFS")
|
||||
|
||||
add_subdirectory(SageOldSrc)
|
||||
add_subdirectory(SageNewSrc)
|
||||
add_subdirectory(SageLib)
|
||||
add_subdirectory(Parser)
|
||||
|
||||
add_definitions("-D __SPF_BUILT_IN_FDVM")
|
||||
add_definitions("-D __SPF_BUILT_IN_PARSER")
|
||||
add_definitions("-D __SPF_BUILT_IN_PPPA")
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(Sapfor_F SageNewSrc SageLib SageOldSrc)
|
||||
elseif(APPLE)
|
||||
target_link_libraries(Sapfor_F SageNewSrc SageLib SageOldSrc pthread)
|
||||
elseif(UNIX)
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0)
|
||||
target_link_libraries(Sapfor_F SageNewSrc SageLib SageOldSrc pthread stdc++fs)
|
||||
else()
|
||||
target_link_libraries(Sapfor_F SageNewSrc SageLib SageOldSrc pthread)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#install(TARGETS <name.exe/dll>
|
||||
# LIBRARY DESTINATION <name_f>
|
||||
# RUNTIME DESTINATION <name_f>)
|
||||
83
Sapfor/FDVM/CMakeLists.txt
Normal file
83
Sapfor/FDVM/CMakeLists.txt
Normal file
@@ -0,0 +1,83 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set(project FDVM)
|
||||
#set(CMAKE_C_STANDARD 11)
|
||||
#also named as libSage++
|
||||
if (TARGET ${project})
|
||||
return()
|
||||
endif ()
|
||||
project(${project})
|
||||
message("processing ${project}")
|
||||
|
||||
# Read pathes to external sapfor directories
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../paths.txt")
|
||||
message("Found paths.txt, using custom paths.")
|
||||
FILE(STRINGS ../paths.txt SAPFOR_PATHS)
|
||||
else ()
|
||||
message("Not found paths.txt, using default paths.")
|
||||
FILE(STRINGS ../paths.default.txt SAPFOR_PATHS)
|
||||
endif ()
|
||||
foreach (NameAndValue ${SAPFOR_PATHS})
|
||||
# Strip leading spaces
|
||||
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
|
||||
# Find variable name
|
||||
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
|
||||
# Find the value
|
||||
string(REPLACE "${Name}=" "" Value ${NameAndValue})
|
||||
# Set the variable, note the ../ because we are deeper than the file
|
||||
set(${Name} "../${Value}")
|
||||
endforeach ()
|
||||
|
||||
set(SOURCE_LIB
|
||||
${sagepp_sources}/libSage++.cpp
|
||||
${sage_include_1}/libSage++.h)
|
||||
|
||||
|
||||
# if not default ${sagepp_sources} must be set in ../paths.txt
|
||||
set(SOURCE_EXE
|
||||
${fdvm_sources}/acc.cpp
|
||||
${fdvm_sources}/acc_across.cpp
|
||||
${fdvm_sources}/acc_across_analyzer.cpp
|
||||
${fdvm_sources}/acc_analyzer.cpp
|
||||
${fdvm_sources}/acc_data.cpp
|
||||
${fdvm_sources}/acc_f2c.cpp
|
||||
${fdvm_sources}/acc_f2c_handlers.cpp
|
||||
${fdvm_sources}/acc_rtc.cpp
|
||||
${fdvm_sources}/acc_rtc.cpp
|
||||
${fdvm_sources}/acc_utilities.cpp
|
||||
${fdvm_sources}/aks_analyzeLoops.cpp
|
||||
${fdvm_sources}/aks_structs.cpp
|
||||
${fdvm_sources}/checkpoint.cpp
|
||||
${fdvm_sources}/debug.cpp
|
||||
${fdvm_sources}/dvm.cpp
|
||||
${fdvm_sources}/calls.cpp
|
||||
${fdvm_sources}/funcall.cpp
|
||||
${fdvm_sources}/help.cpp
|
||||
${fdvm_sources}/hpf.cpp
|
||||
${fdvm_sources}/io.cpp
|
||||
${fdvm_sources}/omp.cpp
|
||||
${fdvm_sources}/ompdebug.cpp
|
||||
${fdvm_sources}/parloop.cpp
|
||||
${fdvm_sources}/stmt.cpp)
|
||||
|
||||
source_group (SageLib FILES ${SOURCE_LIB})
|
||||
|
||||
# if not default ${fdvm_include}, ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
|
||||
include_directories(${fdvm_include} ${sage_include_1} ${sage_include_2})
|
||||
add_executable(FDVM ${SOURCE_EXE} ${SOURCE_LIB})
|
||||
|
||||
if (MSVC_IDE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
|
||||
endif()
|
||||
|
||||
add_definitions("-D _CRT_SECURE_NO_WARNINGS")
|
||||
add_definitions("-D SYS5")
|
||||
add_definitions("-D YYDEBUG")
|
||||
|
||||
add_subdirectory(../SageOldSrc ${CMAKE_CURRENT_BINARY_DIR}/SageOldSrc)
|
||||
add_subdirectory(../SageNewSrc ${CMAKE_CURRENT_BINARY_DIR}/SageNewSrc)
|
||||
target_link_libraries(FDVM SageOldSrc SageNewSrc)
|
||||
66
Sapfor/Parser/CMakeLists.txt
Normal file
66
Sapfor/Parser/CMakeLists.txt
Normal file
@@ -0,0 +1,66 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set(project Parser)
|
||||
#set(CMAKE_C_STANDARD 11)
|
||||
#also named as libSage++
|
||||
if (TARGET ${project})
|
||||
return()
|
||||
endif ()
|
||||
project(${project})
|
||||
message("processing ${project}")
|
||||
|
||||
# Read pathes to external sapfor directories
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../paths.txt")
|
||||
message("Found paths.txt, using custom paths.")
|
||||
FILE(STRINGS ../paths.txt SAPFOR_PATHS)
|
||||
else ()
|
||||
message("Not found paths.txt, using default paths.")
|
||||
FILE(STRINGS ../paths.default.txt SAPFOR_PATHS)
|
||||
endif ()
|
||||
foreach (NameAndValue ${SAPFOR_PATHS})
|
||||
# Strip leading spaces
|
||||
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
|
||||
# Find variable name
|
||||
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
|
||||
# Find the value
|
||||
string(REPLACE "${Name}=" "" Value ${NameAndValue})
|
||||
# Set the variable, note the ../ because we are deeper than the file
|
||||
set(${Name} "../${Value}")
|
||||
endforeach ()
|
||||
|
||||
# if not default ${sagepp_sources} must be set in ../paths.txt
|
||||
set(SOURCE_EXE
|
||||
${parser_sources}/cftn.c
|
||||
${parser_sources}/errors.c
|
||||
${parser_sources}/gram1.tab.c
|
||||
${parser_sources}/hash.c
|
||||
${parser_sources}/init.c
|
||||
${parser_sources}/lexfdvm.c
|
||||
${parser_sources}/lists.c
|
||||
${parser_sources}/low_hpf.c
|
||||
${parser_sources}/misc.c
|
||||
${parser_sources}/stat.c
|
||||
${parser_sources}/sym.c
|
||||
${parser_sources}/types.c
|
||||
${parser_sources}/unparse_hpf.c
|
||||
)
|
||||
|
||||
# if not default ${fdvm_include}, ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
|
||||
include_directories(${fdvm_include} ${sage_include_1} ${sage_include_2})
|
||||
add_executable(Parser ${SOURCE_EXE})
|
||||
|
||||
if (MSVC_IDE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
|
||||
endif()
|
||||
|
||||
add_definitions("-D __SPF")
|
||||
add_definitions("-D _CRT_SECURE_NO_WARNINGS")
|
||||
add_definitions("-D SYS5")
|
||||
add_definitions("-D YYDEBUG")
|
||||
|
||||
add_subdirectory(../SageOldSrc ${CMAKE_CURRENT_BINARY_DIR}/SageOldSrc)
|
||||
target_link_libraries(Parser SageOldSrc)
|
||||
49
Sapfor/SageLib/CMakeLists.txt
Normal file
49
Sapfor/SageLib/CMakeLists.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set(project SageLib)
|
||||
#also named as libSage++
|
||||
if (TARGET ${project})
|
||||
return()
|
||||
endif ()
|
||||
project(${project})
|
||||
message("processing ${project}")
|
||||
|
||||
# Read pathes to external sapfor directories
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../paths.txt")
|
||||
message("Found paths.txt, using custom paths.")
|
||||
FILE(STRINGS ../paths.txt SAPFOR_PATHS)
|
||||
else ()
|
||||
message("Not found paths.txt, using default paths.")
|
||||
FILE(STRINGS ../paths.default.txt SAPFOR_PATHS)
|
||||
endif ()
|
||||
foreach (NameAndValue ${SAPFOR_PATHS})
|
||||
# Strip leading spaces
|
||||
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
|
||||
# Find variable name
|
||||
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
|
||||
# Find the value
|
||||
string(REPLACE "${Name}=" "" Value ${NameAndValue})
|
||||
# Set the variable, note the ../ because we are deeper than the file
|
||||
set(${Name} "../${Value}")
|
||||
endforeach ()
|
||||
|
||||
# if not default ${sagepp_sources} must be set in ../paths.txt
|
||||
set(SOURCE_LIB
|
||||
${sagepp_sources}/libSage++.cpp
|
||||
${sage_include_1}/libSage++.h
|
||||
)
|
||||
|
||||
# if not default ${fdvm_include}, ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
|
||||
include_directories(${fdvm_include} ${sage_include_1} ${sage_include_2})
|
||||
add_library(SageLib STATIC ${SOURCE_LIB})
|
||||
|
||||
add_subdirectory(../SageOldSrc ${CMAKE_CURRENT_BINARY_DIR}/SageOldSrc)
|
||||
target_link_libraries(SageLib SageOldSrc)
|
||||
|
||||
if (MSVC_IDE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
|
||||
endif()
|
||||
52
Sapfor/SageNewSrc/CMakeLists.txt
Normal file
52
Sapfor/SageNewSrc/CMakeLists.txt
Normal file
@@ -0,0 +1,52 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set(project SageNewSrc)
|
||||
#set(CMAKE_C_STANDARD 11)
|
||||
#also named as libSage
|
||||
if (TARGET ${project})
|
||||
return()
|
||||
endif ()
|
||||
project(${project})
|
||||
message("processing ${project}")
|
||||
|
||||
# Read pathes to external sapfor directories
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../paths.txt")
|
||||
message("Found paths.txt, using custom paths.")
|
||||
FILE(STRINGS ../paths.txt SAPFOR_PATHS)
|
||||
else ()
|
||||
message("Not found paths.txt, using default paths.")
|
||||
FILE(STRINGS ../paths.default.txt SAPFOR_PATHS)
|
||||
endif ()
|
||||
foreach (NameAndValue ${SAPFOR_PATHS})
|
||||
# Strip leading spaces
|
||||
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
|
||||
# Find variable name
|
||||
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
|
||||
# Find the value
|
||||
string(REPLACE "${Name}=" "" Value ${NameAndValue})
|
||||
# Set the variable, note the ../ because we are deeper than the file
|
||||
set(${Name} "../${Value}")
|
||||
endforeach ()
|
||||
|
||||
# if not default ${sage_sources} must be set in ../paths.txt
|
||||
set(SOURCE_LIB
|
||||
${sage_sources}/annotate.tab.c
|
||||
${sage_sources}/comments.c
|
||||
${sage_sources}/low_level.c
|
||||
${sage_sources}/toolsann.c
|
||||
${sage_sources}/unparse.c
|
||||
)
|
||||
|
||||
# if not default ${fdvm_include}, ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
|
||||
include_directories(${fdvm_include} ${sage_include_1} ${sage_include_2})
|
||||
add_library(SageNewSrc STATIC ${SOURCE_LIB})
|
||||
|
||||
add_subdirectory(../SageOldSrc ${CMAKE_CURRENT_BINARY_DIR}/SageOldSrc)
|
||||
target_link_libraries(SageNewSrc SageOldSrc)
|
||||
|
||||
if (MSVC_IDE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3")
|
||||
endif()
|
||||
63
Sapfor/SageOldSrc/CMakeLists.txt
Normal file
63
Sapfor/SageOldSrc/CMakeLists.txt
Normal file
@@ -0,0 +1,63 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set(project SageOldSrc)
|
||||
#set(CMAKE_C_STANDARD 11)
|
||||
#also named as libDB
|
||||
if (TARGET ${project})
|
||||
return()
|
||||
endif ()
|
||||
project(${project})
|
||||
message("processing ${project}")
|
||||
|
||||
# Read pathes to external sapfor directories
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../paths.txt")
|
||||
message("Found paths.txt, using custom paths.")
|
||||
FILE(STRINGS ../paths.txt SAPFOR_PATHS)
|
||||
else ()
|
||||
message("Not found paths.txt, using default paths.")
|
||||
FILE(STRINGS ../paths.default.txt SAPFOR_PATHS)
|
||||
endif ()
|
||||
foreach (NameAndValue ${SAPFOR_PATHS})
|
||||
# Strip leading spaces
|
||||
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
|
||||
# Find variable name
|
||||
string(REGEX MATCH "^[^=]+" Name ${NameAndValue})
|
||||
# Find the value
|
||||
string(REPLACE "${Name}=" "" Value ${NameAndValue})
|
||||
# Set the variable, note the ../ because we are deeper than the file
|
||||
set(${Name} "../${Value}")
|
||||
endforeach ()
|
||||
|
||||
# if not default ${libdb_sources} must be set in ../paths.txt
|
||||
set(SOURCE_LIB
|
||||
${libdb_sources}/anal_ind.c
|
||||
${libdb_sources}/db.c
|
||||
${libdb_sources}/dbutils.c
|
||||
${libdb_sources}/db_unp.c
|
||||
${libdb_sources}/db_unp_comm.c
|
||||
${libdb_sources}/db_unp_vpc.c
|
||||
${libdb_sources}/garb_coll.c
|
||||
${libdb_sources}/glob_anal.c
|
||||
${libdb_sources}/ker_fun.c
|
||||
${libdb_sources}/list.c
|
||||
${libdb_sources}/make_nodes.c
|
||||
${libdb_sources}/mod_ref.c
|
||||
${libdb_sources}/ndeps.c
|
||||
${libdb_sources}/readnodes.c
|
||||
${libdb_sources}/sets.c
|
||||
${libdb_sources}/setutils.c
|
||||
${libdb_sources}/symb_alg.c
|
||||
${libdb_sources}/writenodes.c
|
||||
)
|
||||
|
||||
# if not default ${fdvm_include}, ${sage_include_1}, ${sage_include_2} must be set in ../paths.txt
|
||||
include_directories(${fdvm_include} ${sage_include_1} ${sage_include_2})
|
||||
add_library(SageOldSrc STATIC ${SOURCE_LIB})
|
||||
|
||||
if (MSVC_IDE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
|
||||
endif()
|
||||
31
Sapfor/Sapc++/Sapc++.sln
Normal file
31
Sapfor/Sapc++/Sapc++.sln
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2020
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sapc++", "Sapc++\Sapc++.vcxproj", "{DF2410E0-8B0A-420D-AC01-5DAFC460C816}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Debug|x64.Build.0 = Debug|x64
|
||||
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Debug|x86.Build.0 = Debug|Win32
|
||||
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Release|x64.ActiveCfg = Release|x64
|
||||
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Release|x64.Build.0 = Release|x64
|
||||
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Release|x86.ActiveCfg = Release|Win32
|
||||
{DF2410E0-8B0A-420D-AC01-5DAFC460C816}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C1D1EA6C-5160-4B72-8353-388C68748C18}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
468
Sapfor/Sapfor/Makefile
Normal file
468
Sapfor/Sapfor/Makefile
Normal file
@@ -0,0 +1,468 @@
|
||||
########################################################################
|
||||
# Makefile for Sapfor 2017
|
||||
########################################################################
|
||||
|
||||
LIBDIR = ../_lib
|
||||
BINDIR = ../_bin
|
||||
SRCDIR = ../_src
|
||||
|
||||
CXX = g++
|
||||
CC = gcc
|
||||
CFLAGS = -O3 -D__SPF
|
||||
STD=c++11
|
||||
|
||||
REPO_FDVM_BASE = ../../../../dvm/fdvm/trunk/
|
||||
REPO_SPF_BASE = ../_src/
|
||||
|
||||
SAGE_BASE_DIR = $(REPO_FDVM_BASE)Sage/
|
||||
SAGE_SRC_DIR = $(SAGE_BASE_DIR)Sage++/
|
||||
SAGE_SRC_NEW = $(SAGE_BASE_DIR)lib/newsrc/
|
||||
SAGE_SRC_OLD = $(SAGE_BASE_DIR)lib/oldsrc/
|
||||
SAGE_INCL_DIR = $(SAGE_BASE_DIR)/h
|
||||
LIB_INCL = $(SAGE_BASE_DIR)/lib/include
|
||||
|
||||
DVMINCLUDE = $(REPO_FDVM_BASE)/include
|
||||
PARSER_BASE_DIR = $(REPO_FDVM_BASE)parser/
|
||||
|
||||
INLINER_BASE_DIR = $(REPO_FDVM_BASE)InlineExpansion/
|
||||
|
||||
all: $(LIBDIR)/libPred.a $(LIBDIR)/libSage++.a $(LIBDIR)/SageNewSrc.a $(LIBDIR)/SageOldSrc.a $(BINDIR)/Parser $(BINDIR)/Inliner $(BINDIR)/Sapfor
|
||||
|
||||
#Make Predictor
|
||||
PS=$(REPO_SPF_BASE)Predictor/Lib/
|
||||
PRED_OBJ_C=adler32.o compress.o crc32.o deflate.o gzio.o infblock.o infcodes.o inffast.o inflate.o inftrees.o infutil.o \
|
||||
trees.o uncompr.o zutil.o
|
||||
PRED_SOURCE_C=$(PS)adler32.c $(PS)compress.c $(PS)crc32.c $(PS)deflate.c $(PS)gzio.c $(PS)infblock.c $(PS)infcodes.c $(PS)inffast.c \
|
||||
$(PS)inflate.c $(PS)inftrees.c $(PS)infutil.c $(PS)trees.c $(PS)uncompr.c $(PS)zutil.c
|
||||
|
||||
PRED_OBJ_CPP=AlignAxis.o AMView.o BGroup.o Block.o CallParams.o CommCost.o DArray.o DimBound.o DistAxis.o Event.o FuncCall.o \
|
||||
Interval.o IntervalTemplate.o LoopBlock.o LoopLS.o Ls.o ModelDArray.o ModelInterval.o ModelIO.o ModelMPS_AM.o ModelParLoop.o \
|
||||
ModelReduct.o ModelRegular.o ModelRemAccess.o ModelShadow.o ParLoop.o ParseString.o Processor.o Ps.o RedGroup.o RedVar.o \
|
||||
RemAccessBuf.o Space.o TraceLine.o Vm.o intersection.o predictor.o
|
||||
PRED_SOURCE_CPP=$(PS)AlignAxis.cpp $(PS)AMView.cpp $(PS)BGroup.cpp $(PS)Block.cpp $(PS)CallParams.cpp $(PS)CommCost.cpp $(PS)DArray.cpp \
|
||||
$(PS)DimBound.cpp $(PS)DistAxis.cpp $(PS)Event.cpp $(PS)FuncCall.cpp $(PS)Interval.cpp $(PS)IntervalTemplate.cpp $(PS)LoopBlock.cpp \
|
||||
$(PS)LoopLS.cpp $(PS)Ls.cpp $(PS)ModelDArray.cpp $(PS)ModelInterval.cpp $(PS)ModelIO.cpp $(PS)ModelMPS_AM.cpp $(PS)ModelParLoop.cpp \
|
||||
$(PS)ModelReduct.cpp $(PS)ModelRegular.cpp $(PS)ModelRemAccess.cpp $(PS)ModelShadow.cpp $(PS)ParLoop.cpp $(PS)ParseString.cpp \
|
||||
$(PS)Processor.cpp $(PS)Ps.cpp $(PS)RedGroup.cpp $(PS)RedVar.cpp $(PS)RemAccessBuf.cpp $(PS)Space.cpp $(PS)TraceLine.cpp $(PS)Vm.cpp \
|
||||
$(PS)intersection.cpp $(PS)predictor.cpp
|
||||
AlignAxis.o: $(PS)AlignAxis.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)AlignAxis.cpp
|
||||
AMView.o: $(PS)AMView.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)AMView.cpp
|
||||
BGroup.o: $(PS)BGroup.cpp
|
||||
$(CXX) $(CFLAGS) -std=$(STD) -c $(PS)BGroup.cpp
|
||||
Block.o: $(PS)Block.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)Block.cpp
|
||||
CallParams.o: $(PS)CallParams.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)CallParams.cpp
|
||||
CommCost.o: $(PS)CommCost.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)CommCost.cpp
|
||||
DArray.o: $(PS)DArray.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)DArray.cpp
|
||||
DimBound.o: $(PS)DimBound.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)DimBound.cpp
|
||||
DistAxis.o: $(PS)DistAxis.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)DistAxis.cpp
|
||||
Event.o: $(PS)Event.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)Event.cpp
|
||||
FuncCall.o: $(PS)FuncCall.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)FuncCall.cpp
|
||||
Interval.o: $(PS)Interval.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)Interval.cpp
|
||||
IntervalTemplate.o: $(PS)IntervalTemplate.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)IntervalTemplate.cpp
|
||||
LoopBlock.o: $(PS)LoopBlock.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)LoopBlock.cpp
|
||||
LoopLS.o: $(PS)LoopLS.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)LoopLS.cpp
|
||||
Ls.o: $(PS)Ls.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)Ls.cpp
|
||||
ModelDArray.o: $(PS)ModelDArray.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)ModelDArray.cpp
|
||||
ModelInterval.o: $(PS)ModelInterval.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)ModelInterval.cpp
|
||||
ModelIO.o: $(PS)ModelIO.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)ModelIO.cpp
|
||||
ModelMPS_AM.o: $(PS)ModelMPS_AM.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)ModelMPS_AM.cpp
|
||||
ModelParLoop.o: $(PS)ModelParLoop.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)ModelParLoop.cpp
|
||||
ModelReduct.o: $(PS)ModelReduct.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)ModelReduct.cpp
|
||||
ModelRegular.o: $(PS)ModelRegular.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)ModelRegular.cpp
|
||||
ModelRemAccess.o: $(PS)ModelRemAccess.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)ModelRemAccess.cpp
|
||||
ModelShadow.o: $(PS)ModelShadow.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)ModelShadow.cpp
|
||||
ParLoop.o: $(PS)ParLoop.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)ParLoop.cpp
|
||||
ParseString.o: $(PS)ParseString.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)ParseString.cpp
|
||||
Processor.o: $(PS)Processor.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)Processor.cpp
|
||||
Ps.o: $(PS)Ps.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)Ps.cpp
|
||||
RedGroup.o: $(PS)RedGroup.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)RedGroup.cpp
|
||||
RedVar.o: $(PS)RedVar.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)RedVar.cpp
|
||||
RemAccessBuf.o: $(PS)RemAccessBuf.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)RemAccessBuf.cpp
|
||||
Space.o: $(PS)Space.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)Space.cpp
|
||||
TraceLine.o: $(PS)TraceLine.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)TraceLine.cpp
|
||||
Vm.o: $(PS)Vm.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)Vm.cpp
|
||||
intersection.o: $(PS)intersection.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)intersection.cpp
|
||||
predictor.o: $(PS)predictor.cpp
|
||||
$(CXX) $(CFLAGS) -c $(PS)predictor.cpp
|
||||
|
||||
adler32.o: $(PS)adler32.c
|
||||
$(CC) $(CFLAGS) -c $(PS)adler32.c
|
||||
compress.o: $(PS)compress.c
|
||||
$(CC) $(CFLAGS) -c $(PS)compress.c
|
||||
crc32.o: $(PS)crc32.c
|
||||
$(CC) $(CFLAGS) -c $(PS)crc32.c
|
||||
deflate.o: $(PS)deflate.c
|
||||
$(CC) $(CFLAGS) -c $(PS)deflate.c
|
||||
gzio.o: $(PS)gzio.c
|
||||
$(CC) $(CFLAGS) -c $(PS)gzio.c
|
||||
infblock.o: $(PS)infblock.c
|
||||
$(CC) $(CFLAGS) -c $(PS)infblock.c
|
||||
infcodes.o: $(PS)infcodes.c
|
||||
$(CC) $(CFLAGS) -c $(PS)infcodes.c
|
||||
inffast.o: $(PS)inffast.c
|
||||
$(CC) $(CFLAGS) -c $(PS)inffast.c
|
||||
inflate.o: $(PS)inflate.c
|
||||
$(CC) $(CFLAGS) -c $(PS)inflate.c
|
||||
inftrees.o: $(PS)inftrees.c
|
||||
$(CC) $(CFLAGS) -c $(PS)inftrees.c
|
||||
infutil.o: $(PS)infutil.c
|
||||
$(CC) $(CFLAGS) -c $(PS)infutil.c
|
||||
trees.o: $(PS)trees.c
|
||||
$(CC) $(CFLAGS) -c $(PS)trees.c
|
||||
uncompr.o: $(PS)uncompr.c
|
||||
$(CC) $(CFLAGS) -c $(PS)uncompr.c
|
||||
zutil.o: $(PS)zutil.c
|
||||
$(CC) $(CFLAGS) -c $(PS)zutil.c
|
||||
|
||||
$(LIBDIR)/libPred.a: $(PRED_OBJ_C) $(PRED_OBJ_CPP)
|
||||
ar qc $(LIBDIR)/libPred.a $(PRED_OBJ_C) $(PRED_OBJ_CPP)
|
||||
|
||||
#Make SAGE++
|
||||
libSage++.o: $(SAGE_SRC_DIR)libSage++.cpp $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def $(LIB_INCL)/libSage++.h
|
||||
$(CXX) $(CFLAGS) -c $(SAGE_SRC_DIR)libSage++.cpp -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
$(LIBDIR)/libSage++.a: libSage++.o
|
||||
ar qc $(LIBDIR)/libSage++.a libSage++.o
|
||||
|
||||
#Make SAGE newsrc
|
||||
low_level.o: $(SAGE_SRC_NEW)low_level.c $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_NEW)low_level.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
unparse.o: $(SAGE_SRC_NEW)unparse.c $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def $(LIB_INCL)/unparse.def $(LIB_INCL)/unparseC++.def
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_NEW)unparse.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
annotate.tab.o: $(SAGE_SRC_NEW)annotate.tab.c $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_NEW)annotate.tab.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
comments.o: $(SAGE_SRC_NEW)comments.c $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_NEW)comments.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
toolsann.o: $(SAGE_SRC_NEW)toolsann.c $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_NEW)toolsann.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
|
||||
$(LIBDIR)/SageNewSrc.a: low_level.o unparse.o annotate.tab.o comments.o toolsann.o $(LIB_INCL)/macro.h $(LIB_INCL)/bif_node.def $(LIB_INCL)/type.def $(LIB_INCL)/symb.def
|
||||
ar qc $(LIBDIR)/SageNewSrc.a low_level.o unparse.o annotate.tab.o comments.o toolsann.o
|
||||
|
||||
#Make SAGE oldsrc
|
||||
OLD_SRC_OBJS = anal_ind.o db.o db_unp.o db_unp_vpc.o dbutils.o garb_coll.o glob_anal.o ker_fun.o \
|
||||
list.o make_nodes.o mod_ref.o ndeps.o readnodes.o sets.o setutils.o symb_alg.o writenodes.o
|
||||
|
||||
H = $(SAGE_INCL_DIR)
|
||||
anal_ind.o: $(SAGE_SRC_OLD)anal_ind.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)anal_ind.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
db.o: $(SAGE_SRC_OLD)db.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)db.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
db_unp.o: $(SAGE_SRC_OLD)db_unp.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)db_unp.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
db_unp_vpc.o: $(SAGE_SRC_OLD)db_unp_vpc.c $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/db.h $(H)/vparse.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)db_unp_vpc.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
dbutils.o: $(SAGE_SRC_OLD)dbutils.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)dbutils.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
garb_coll.o: $(SAGE_SRC_OLD)garb_coll.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)garb_coll.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
glob_anal.o: $(SAGE_SRC_OLD)glob_anal.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)glob_anal.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
ker_fun.o: $(SAGE_SRC_OLD)ker_fun.c $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)ker_fun.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
list.o: $(SAGE_SRC_OLD)list.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/list.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)list.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
make_nodes.o: $(SAGE_SRC_OLD)make_nodes.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)make_nodes.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
mod_ref.o: $(SAGE_SRC_OLD)mod_ref.c $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/vparse.h $(H)/db.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)mod_ref.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
ndeps.o: $(SAGE_SRC_OLD)ndeps.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)ndeps.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
readnodes.o: $(SAGE_SRC_OLD)readnodes.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/dep_str.h $(H)/dep.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)readnodes.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
sets.o: $(SAGE_SRC_OLD)sets.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)sets.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
setutils.o: $(SAGE_SRC_OLD)setutils.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)setutils.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
symb_alg.o: $(SAGE_SRC_OLD)symb_alg.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)symb_alg.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
writenodes.o: $(SAGE_SRC_OLD)writenodes.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/dep_str.h $(H)/dep.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(SAGE_SRC_OLD)writenodes.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
|
||||
$(LIBDIR)/SageOldSrc.a: $(OLD_SRC_OBJS)
|
||||
ar qc $(LIBDIR)/SageOldSrc.a $(OLD_SRC_OBJS)
|
||||
|
||||
#Make Parser
|
||||
PARSER_OBJS = cftn.o errors.o hash.o init.o lexfdvm.o lists.o misc.o stat.o types.o gram1.tab.o sym.o low_hpf.o unparse_hpf.o
|
||||
$(BINDIR)/Parser: $(PARSER_OBJS) $(LIBDIR)/SageOldSrc.a
|
||||
$(CXX) -o $(BINDIR)/Parser $(PARSER_OBJS) $(LIBDIR)/SageOldSrc.a
|
||||
|
||||
cftn.o: $(PARSER_BASE_DIR)cftn.c $(H)/db.h $(H)/defs.h $(H)/tag $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)cftn.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
errors.o: $(PARSER_BASE_DIR)errors.c $(H)/defs.h $(H)/tag $(H)/symb.h $(DVMINCLUDE)/extern.h $(H)/db.h $(H)/bif.h $(H)/ll.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)errors.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
hash.o: $(PARSER_BASE_DIR)hash.c $(H)/defs.h $(H)/symb.h $(H)/defines.h $(DVMINCLUDE)/extern.h $(H)/db.h $(H)/bif.h $(H)/ll.h $(H)/sets.h $(H)/tag
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)hash.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
init.o: $(PARSER_BASE_DIR)init.c $(DVMINCLUDE)/inc.h $(H)/defs.h $(H)/bif.h $(H)/defines.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/db.h $(H)/tag
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)init.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
lexfdvm.o: $(PARSER_BASE_DIR)lexfdvm.c $(DVMINCLUDE)/extern.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)lexfdvm.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
lists.o: $(PARSER_BASE_DIR)lists.c $(H)/defs.h $(H)/ll.h $(H)/symb.h $(H)/bif.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)lists.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
misc.o: $(PARSER_BASE_DIR)misc.c $(H)/defs.h $(H)/tag $(H)/defines.h $(H)/db.h $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)misc.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
stat.o: $(PARSER_BASE_DIR)stat.c $(H)/defs.h $(H)/bif.h $(H)/ll.h $(H)/symb.h $(H)/sets.h $(H)/defines.h $(DVMINCLUDE)/extern.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)stat.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
sym.o: $(PARSER_BASE_DIR)sym.c $(H)/defs.h $(H)/tag $(H)/symb.h $(H)/defines.h $(H)/bif.h $(DVMINCLUDE)/extern.h $(H)/db.h $(H)/ll.h $(H)/sets.h $(DVMINCLUDE)/fdvm.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)sym.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
types.o: $(PARSER_BASE_DIR)types.c $(H)/defs.h $(H)/ll.h $(H)/symb.h
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)types.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
low_hpf.o: $(PARSER_BASE_DIR)low_hpf.c $(DVMINCLUDE)/dvm_tag.h $(TOOLBOX_HDR)
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)low_hpf.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
unparse_hpf.o: $(PARSER_BASE_DIR)unparse_hpf.c $(DVMINCLUDE)/dvm_tag.h $(TOOLBOX_HDR) $(DVMINCLUDE)/unparse.hpf
|
||||
$(CC) $(CFLAGS) -c -DSYS5 $(PARSER_BASE_DIR)unparse_hpf.c -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(DVMINCLUDE)
|
||||
gram1.tab.o: $(PARSER_BASE_DIR)gram1.tab.c
|
||||
$(CC) $(CFLAGS) -c -DSYS5 -DYYDEBUG $(PARSER_BASE_DIR)gram1.tab.c -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
|
||||
#Make Inliner
|
||||
$(BINDIR)/Inliner: inl_exp.o inliner.o hlp.o $(LIBDIR)/libSage++.a $(LIBDIR)/SageNewSrc.a $(LIBDIR)/SageOldSrc.a
|
||||
$(CXX) -o $(BINDIR)/Inliner inl_exp.o inliner.o hlp.o $(LIBDIR)/libSage++.a $(LIBDIR)/SageNewSrc.a $(LIBDIR)/SageOldSrc.a
|
||||
|
||||
inl_exp.o: $(INLINER_BASE_DIR)inl_exp.cpp $(INLINER_BASE_DIR)inline.h
|
||||
$(CXX) $(CFLAGS) -std=$(STD) -c $(INLINER_BASE_DIR)inl_exp.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
inliner.o: $(INLINER_BASE_DIR)inliner.cpp $(INLINER_BASE_DIR)inline.h
|
||||
$(CXX) $(CFLAGS) -std=$(STD) -c $(INLINER_BASE_DIR)inliner.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
hlp.o: $(INLINER_BASE_DIR)hlp.cpp $(INLINER_BASE_DIR)inline.h
|
||||
$(CXX) $(CFLAGS) -std=$(STD) -c $(INLINER_BASE_DIR)hlp.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
|
||||
|
||||
#Make Sapfor
|
||||
SAPFOR_OBJ = private_analyzer.o utils.o SgUtils.o Sapfor.o CorrectVarDecl.o IncludeChecker.o LoopChecker.o ParRegions.o \
|
||||
enddo_loop_converter.o array_assign_to_loop.o allocations_prepoc.o directive_creator.o insert_directive.o loop_analyzer.o spf_directive_preproc.o \
|
||||
graph_loops.o graph_loops_base.o graph_calls.o expr_transform.o CreateDistributionDirs.o DvmhDirective.o DvmhDirectiveBase.o DirectiveAnalyzer.o \
|
||||
acc_analyzer.o acc_data.o calls.o acc_utilities.o directive_parser.o GraphCSR.o Distribution.o Cycle.o \
|
||||
annotationDriver.o arrayRef.o computeInducVar.o constanteProp.o controlFlow.o defUse.o dependence.o depGraph.o \
|
||||
depInterface.o flowAnalysis.o intrinsic.o invariant.o loopTransform.o set.o \
|
||||
add-assert.o affine.o cover.o ddomega.o ddomega-build.o ddomega-use.o debug.o ip.o kill.o refine.o sagedriver.o \
|
||||
dep_analyzer.o remote_access.o VerifySageStructures.o loop_transform.o PredictScheme.o control_flow_graph_part.o \
|
||||
shadow.o private_arrays_breeder.o resolve_par_reg_conflicts.o loops_splitter.o loops_combiner.o CreateInterTree.o gcov_info.o gCov_parser.o \
|
||||
graph_calls_base.o directive_creator_base.o PredictorModel.o createParallelRegions.o \
|
||||
expand_extract_reg.o RationalNum.o Array.o DvmhRegionInserter.o uniq_call_chain_dup.o
|
||||
|
||||
$(BINDIR)/Sapfor: $(SAPFOR_OBJ) $(LIBDIR)/libSage++.a $(LIBDIR)/SageNewSrc.a $(LIBDIR)/SageOldSrc.a
|
||||
$(CXX) -fopenmp -o $(BINDIR)/Sapfor $(SAPFOR_OBJ) $(LIBDIR)/libSage++.a $(LIBDIR)/SageNewSrc.a $(LIBDIR)/SageOldSrc.a $(LIBDIR)/libPred.a
|
||||
|
||||
expand_extract_reg.o: $(REPO_SPF_BASE)ParallelizationRegions/expand_extract_reg.cpp $(REPO_SPF_BASE)ParallelizationRegions/expand_extract_reg.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)ParallelizationRegions/expand_extract_reg.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) $(TR_LIB_INC)
|
||||
createParallelRegions.o: $(REPO_SPF_BASE)DynamicAnalysis/createParallelRegions.cpp $(REPO_SPF_BASE)DynamicAnalysis/createParallelRegions.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)DynamicAnalysis/createParallelRegions.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
gcov_info.o: $(REPO_SPF_BASE)DynamicAnalysis/gcov_info.cpp $(REPO_SPF_BASE)DynamicAnalysis/gcov_info.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)DynamicAnalysis/gcov_info.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
gCov_parser.o: $(REPO_SPF_BASE)DynamicAnalysis/gCov_parser.cpp $(REPO_SPF_BASE)DynamicAnalysis/gCov_parser_func.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)DynamicAnalysis/gCov_parser.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
CreateInterTree.o: $(REPO_SPF_BASE)CreateInterTree/CreateInterTree.cpp $(REPO_SPF_BASE)CreateInterTree/CreateInterTree.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)CreateInterTree/CreateInterTree.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
RationalNum.o: $(REPO_SPF_BASE)Utils/RationalNum.cpp $(REPO_SPF_BASE)Utils/RationalNum.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Utils/RationalNum.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
utils.o: $(REPO_SPF_BASE)Utils/utils.cpp $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)Utils/utils.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Utils/utils.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
SgUtils.o: $(REPO_SPF_BASE)Utils/SgUtils.cpp $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)Utils/utils.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Utils/SgUtils.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
directive_parser.o: $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.cpp $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h $(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
Sapfor.o: $(REPO_SPF_BASE)Sapfor.cpp $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)LoopConverter/enddo_loop_converter.h \
|
||||
$(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h $(REPO_SPF_BASE)GraphCall/graph_calls.h $(REPO_SPF_BASE)GraphLoop/graph_loops.h \
|
||||
$(REPO_SPF_BASE)DirectiveAnalyzer/DirectiveAnalyzer.h $(REPO_SPF_BASE)VerificationCode/verifications.h $(REPO_SPF_BASE)Distribution/CreateDistributionDirs.h \
|
||||
$(REPO_SPF_BASE)PrivateAnalyzer/private_analyzer.h $(REPO_SPF_BASE)Sapfor.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Sapfor.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) $(TR_LIB_INC)
|
||||
CorrectVarDecl.o: $(REPO_SPF_BASE)VerificationCode/CorrectVarDecl.cpp $(REPO_SPF_BASE)VerificationCode/verifications.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)VerificationCode/CorrectVarDecl.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
IncludeChecker.o: $(REPO_SPF_BASE)VerificationCode/IncludeChecker.cpp $(REPO_SPF_BASE)VerificationCode/verifications.h $(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)Distribution/DvmhDirective.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)VerificationCode/IncludeChecker.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
LoopChecker.o: $(REPO_SPF_BASE)VerificationCode/LoopChecker.cpp $(REPO_SPF_BASE)VerificationCode/verifications.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)VerificationCode/LoopChecker.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
VerifySageStructures.o: $(REPO_SPF_BASE)VerificationCode/VerifySageStructures.cpp $(REPO_SPF_BASE)VerificationCode/verifications.h $(REPO_SPF_BASE)Utils/utils.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)VerificationCode/VerifySageStructures.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
private_analyzer.o: $(REPO_SPF_BASE)PrivateAnalyzer/private_analyzer.cpp $(REPO_SPF_BASE)PrivateAnalyzer/private_analyzer.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)PrivateAnalyzer/private_analyzer.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
acc_analyzer.o: $(REPO_FDVM_BASE)fdvm/acc_analyzer.cpp $(REPO_FDVM_BASE)include/acc_analyzer.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_FDVM_BASE)fdvm/acc_analyzer.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) -I$(REPO_SPF_BASE)
|
||||
acc_data.o: $(REPO_FDVM_BASE)fdvm/acc_data.cpp
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_FDVM_BASE)fdvm/acc_data.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
acc_utilities.o: $(REPO_FDVM_BASE)fdvm/acc_utilities.cpp
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_FDVM_BASE)fdvm/acc_utilities.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
calls.o: $(REPO_FDVM_BASE)fdvm/calls.cpp
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_FDVM_BASE)fdvm/calls.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
ParRegions.o: $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.cpp $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
resolve_par_reg_conflicts.o: $(REPO_SPF_BASE)ParallelizationRegions/resolve_par_reg_conflicts.cpp $(REPO_SPF_BASE)ParallelizationRegions/resolve_par_reg_conflicts.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)ParallelizationRegions/resolve_par_reg_conflicts.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
enddo_loop_converter.o: $(REPO_SPF_BASE)LoopConverter/enddo_loop_converter.cpp $(REPO_SPF_BASE)LoopConverter/enddo_loop_converter.h $(REPO_SPF_BASE)Utils/errors.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/enddo_loop_converter.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
array_assign_to_loop.o: $(REPO_SPF_BASE)LoopConverter/array_assign_to_loop.cpp $(REPO_SPF_BASE)LoopConverter/array_assign_to_loop.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/array_assign_to_loop.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
uniq_call_chain_dup.o: $(REPO_SPF_BASE)LoopConverter/uniq_call_chain_dup.cpp $(REPO_SPF_BASE)LoopConverter/uniq_call_chain_dup.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/uniq_call_chain_dup.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
loop_transform.o: $(REPO_SPF_BASE)LoopConverter/loop_transform.cpp $(REPO_SPF_BASE)LoopConverter/loop_transform.h $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)GraphLoop/graph_loops.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/loop_transform.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) $(TR_LIB_INC)
|
||||
shadow.o: $(REPO_SPF_BASE)LoopAnalyzer/shadow.cpp $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/shadow.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) $(TR_LIB_INC)
|
||||
|
||||
allocations_prepoc.o: $(REPO_SPF_BASE)LoopAnalyzer/allocations_prepoc.cpp $(REPO_SPF_BASE)Utils/utils.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/allocations_prepoc.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
directive_creator.o: $(REPO_SPF_BASE)LoopAnalyzer/directive_creator.cpp $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.h \
|
||||
$(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Distribution.h \
|
||||
$(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h $(REPO_SPF_BASE)Utils/utils.h \
|
||||
$(REPO_SPF_BASE)Sapfor.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/directive_creator.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
$(TR_LIB_INC)
|
||||
directive_creator_base.o: $(REPO_SPF_BASE)LoopAnalyzer/directive_creator_base.cpp $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.h \
|
||||
$(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Distribution.h \
|
||||
$(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h $(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)LoopAnalyzer/directive_creator.h \
|
||||
$(REPO_SPF_BASE)Sapfor.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/directive_creator_base.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL) $(TR_LIB_INC)
|
||||
insert_directive.o: $(REPO_SPF_BASE)LoopAnalyzer/insert_directive.cpp $(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h \
|
||||
$(REPO_SPF_BASE)Distribution/Distribution.h $(REPO_SPF_BASE)Distribution/DvmhDirective.h $(REPO_SPF_BASE)Utils/errors.h \
|
||||
$(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h $(REPO_SPF_BASE)Utils/utils.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/insert_directive.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
loop_analyzer.o: $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.cpp $(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h \
|
||||
$(REPO_SPF_BASE)Distribution/Distribution.h $(REPO_SPF_BASE)ParallelizationRegions/ParRegions.h $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h \
|
||||
$(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h $(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)GraphCall/graph_calls.h $(REPO_SPF_BASE)ExpressionTransform/expr_transform.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
remote_access.o: $(REPO_SPF_BASE)LoopAnalyzer/remote_access.cpp $(REPO_SPF_BASE)Distribution/Arrays.h \
|
||||
$(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h \
|
||||
$(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)GraphCall/graph_calls.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/remote_access.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
dep_analyzer.o: $(REPO_SPF_BASE)LoopAnalyzer/dep_analyzer.cpp $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h $(REPO_SPF_BASE)Utils/utils.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/dep_analyzer.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
spf_directive_preproc.o: $(REPO_SPF_BASE)LoopAnalyzer/spf_directive_preproc.cpp
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopAnalyzer/spf_directive_preproc.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
graph_loops.o: $(REPO_SPF_BASE)GraphLoop/graph_loops.cpp $(REPO_SPF_BASE)GraphLoop/graph_loops.h $(REPO_SPF_BASE)GraphCall/graph_calls.h \
|
||||
$(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Distribution.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)GraphLoop/graph_loops.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
graph_loops_base.o: $(REPO_SPF_BASE)GraphLoop/graph_loops_base.cpp $(REPO_SPF_BASE)GraphLoop/graph_loops.h $(REPO_SPF_BASE)GraphCall/graph_calls.h \
|
||||
$(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Distribution.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)GraphLoop/graph_loops_base.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
PredictScheme.o: $(REPO_SPF_BASE)Predictor/PredictScheme.cpp $(REPO_SPF_BASE)Predictor/PredictScheme.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Predictor/PredictScheme.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
PredictorModel.o: $(REPO_SPF_BASE)Predictor/PredictorModel.cpp $(REPO_SPF_BASE)Predictor/PredictorModel.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Predictor/PredictorModel.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
graph_calls.o: $(REPO_SPF_BASE)GraphCall/graph_calls.cpp $(REPO_SPF_BASE)GraphLoop/graph_loops.h $(REPO_SPF_BASE)GraphCall/graph_calls.h $(REPO_SPF_BASE)LoopAnalyzer/directive_parser.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)GraphCall/graph_calls.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
graph_calls_base.o: $(REPO_SPF_BASE)GraphCall/graph_calls_base.cpp $(REPO_SPF_BASE)GraphCall/graph_calls_func.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)GraphCall/graph_calls_base.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
expr_transform.o: $(REPO_SPF_BASE)ExpressionTransform/expr_transform.cpp $(REPO_FDVM_BASE)include/acc_analyzer.h $(REPO_SPF_BASE)ExpressionTransform/expr_transform.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)ExpressionTransform/expr_transform.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
control_flow_graph_part.o: $(REPO_SPF_BASE)ExpressionTransform/control_flow_graph_part.cpp $(REPO_FDVM_BASE)include/acc_analyzer.h $(REPO_SPF_BASE)ExpressionTransform/expr_transform.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)ExpressionTransform/control_flow_graph_part.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
CreateDistributionDirs.o: $(REPO_SPF_BASE)Distribution/CreateDistributionDirs.cpp $(REPO_SPF_BASE)Distribution/Distribution.h $(REPO_SPF_BASE)Distribution/GraphCSR.h \
|
||||
$(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)GraphLoop/graph_loops.h $(REPO_SPF_BASE)LoopAnalyzer/loop_analyzer.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/CreateDistributionDirs.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
DvmhDirective.o: $(REPO_SPF_BASE)Distribution/DvmhDirective.cpp $(REPO_SPF_BASE)Distribution/DvmhDirective.h $(REPO_SPF_BASE)Utils/utils.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/DvmhDirective.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
DvmhDirectiveBase.o: $(REPO_SPF_BASE)Distribution/DvmhDirectiveBase.cpp $(REPO_SPF_BASE)Distribution/DvmhDirectiveBase.h $(REPO_SPF_BASE)Utils/utils.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/DvmhDirectiveBase.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
DirectiveAnalyzer.o: $(REPO_SPF_BASE)DirectiveAnalyzer/DirectiveAnalyzer.cpp $(REPO_SPF_BASE)Distribution/DvmhDirective.h $(REPO_SPF_BASE)GraphLoop/graph_loops.h \
|
||||
$(REPO_SPF_BASE)DirectiveAnalyzer/DirectiveAnalyzer.h $(REPO_SPF_BASE)Utils/utils.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)DirectiveAnalyzer/DirectiveAnalyzer.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
Cycle.o: $(REPO_SPF_BASE)Distribution/Cycle.cpp $(REPO_SPF_BASE)Distribution/Cycle.h $(REPO_SPF_BASE)Distribution/DvmhDirective.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/Cycle.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
Distribution.o: $(REPO_SPF_BASE)Distribution/Distribution.cpp $(REPO_SPF_BASE)Distribution/Distribution.h $(REPO_SPF_BASE)Distribution/DvmhDirective.h \
|
||||
$(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Array.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/Distribution.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
Array.o: $(REPO_SPF_BASE)Distribution/Array.cpp $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Array.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/Array.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
GraphCSR.o: $(REPO_SPF_BASE)Distribution/GraphCSR.cpp $(REPO_SPF_BASE)Distribution/GraphCSR.h $(REPO_SPF_BASE)Distribution/DvmhDirective.h \
|
||||
$(REPO_SPF_BASE)Utils/utils.h $(REPO_SPF_BASE)Utils/errors.h $(REPO_SPF_BASE)Distribution/Arrays.h $(REPO_SPF_BASE)Distribution/Array.h \
|
||||
$(REPO_SPF_BASE)Distribution/Cycle.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)Distribution/GraphCSR.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
|
||||
annotationDriver.o: $(REPO_SPF_BASE)SageAnalysisTool/annotationDriver.cpp $(REPO_SPF_BASE)SageAnalysisTool/annotationDriver.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/annotationDriver.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
arrayRef.o: $(REPO_SPF_BASE)SageAnalysisTool/arrayRef.cpp $(REPO_SPF_BASE)SageAnalysisTool/arrayRef.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/arrayRef.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
computeInducVar.o: $(REPO_SPF_BASE)SageAnalysisTool/computeInducVar.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/computeInducVar.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
constanteProp.o: $(REPO_SPF_BASE)SageAnalysisTool/constanteProp.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/constanteProp.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
controlFlow.o: $(REPO_SPF_BASE)SageAnalysisTool/controlFlow.cpp
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/controlFlow.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
defUse.o: $(REPO_SPF_BASE)SageAnalysisTool/defUse.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/defUse.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
dependence.o: $(REPO_SPF_BASE)SageAnalysisTool/dependence.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h $(REPO_SPF_BASE)SageAnalysisTool/dependence.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/dependence.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
depGraph.o: $(REPO_SPF_BASE)SageAnalysisTool/depGraph.cpp
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/depGraph.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
depInterface.o: $(REPO_SPF_BASE)SageAnalysisTool/depInterface.cpp
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/depInterface.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
flowAnalysis.o: $(REPO_SPF_BASE)SageAnalysisTool/flowAnalysis.cpp
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/flowAnalysis.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
intrinsic.o: $(REPO_SPF_BASE)SageAnalysisTool/intrinsic.cpp $(REPO_SPF_BASE)SageAnalysisTool/intrinsic.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/intrinsic.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
invariant.o: $(REPO_SPF_BASE)SageAnalysisTool/invariant.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/invariant.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
loopTransform.o: $(REPO_SPF_BASE)SageAnalysisTool/loopTransform.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/loopTransform.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
set.o: $(REPO_SPF_BASE)SageAnalysisTool/set.cpp $(REPO_SPF_BASE)SageAnalysisTool/set.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)SageAnalysisTool/set.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
|
||||
add-assert.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/add-assert.cpp
|
||||
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/add-assert.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
affine.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/affine.cpp
|
||||
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/affine.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
cover.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/cover.cpp
|
||||
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/cover.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
ddomega.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega.cpp
|
||||
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
ddomega-build.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega-build.cpp
|
||||
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega-build.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
ddomega-use.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega-use.cpp
|
||||
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ddomega-use.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
debug.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/debug.cpp
|
||||
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/debug.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
ip.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ip.cpp
|
||||
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/ip.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
kill.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/kill.cpp
|
||||
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/kill.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
refine.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/refine.cpp
|
||||
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/refine.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
sagedriver.o: $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/sagedriver.cpp
|
||||
$(CXX) $(CFLAGS) -c $(REPO_SPF_BASE)SageAnalysisTool/OmegaForSage/sagedriver.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
private_arrays_breeder.o: $(REPO_SPF_BASE)LoopConverter/private_arrays_breeder.cpp $(REPO_SPF_BASE)LoopConverter/private_arrays_breeder.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/private_arrays_breeder.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
loops_splitter.o: $(REPO_SPF_BASE)LoopConverter/loops_splitter.cpp $(REPO_SPF_BASE)LoopConverter/loops_splitter.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/loops_splitter.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
DvmhRegionInserter.o: $(REPO_SPF_BASE)DvmhRegions/DvmhRegionInserter.cpp $(REPO_SPF_BASE)DvmhRegions/DvmhRegionInserter.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)DvmhRegions/DvmhRegionInserter.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
loops_combiner.o: $(REPO_SPF_BASE)LoopConverter/loops_combiner.cpp $(REPO_SPF_BASE)LoopConverter/loops_combiner.h
|
||||
$(CXX) $(CFLAGS) -c -std=$(STD) $(REPO_SPF_BASE)LoopConverter/loops_combiner.cpp -I$(DVMINCLUDE) -I$(SAGE_INCL_DIR) -I$(LIB_INCL)
|
||||
|
||||
clean:
|
||||
rm -rf *.o
|
||||
|
||||
cleanall:
|
||||
rm -rf *.o ../_lib/*.a
|
||||
1246
Sapfor/_src/CFGraph/CFGraph.cpp
Normal file
1246
Sapfor/_src/CFGraph/CFGraph.cpp
Normal file
File diff suppressed because it is too large
Load Diff
151
Sapfor/_src/CFGraph/CFGraph.h
Normal file
151
Sapfor/_src/CFGraph/CFGraph.h
Normal file
@@ -0,0 +1,151 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "IR.h"
|
||||
|
||||
namespace SAPFOR
|
||||
{
|
||||
enum CFG_VAL : int { KILL_ALL = -1, UNINIT = -2 };
|
||||
|
||||
class IR_Block;
|
||||
class Argument;
|
||||
class Instruction;
|
||||
|
||||
class BasicBlock
|
||||
{
|
||||
static int lastNumBlock;
|
||||
private:
|
||||
int num;
|
||||
std::vector<IR_Block*> instructions;
|
||||
|
||||
std::vector<BasicBlock*> next;
|
||||
std::vector<BasicBlock*> prev;
|
||||
|
||||
//reaching definition
|
||||
std::map<SAPFOR::Argument*, std::set<int>> RD_in, RD_out;
|
||||
|
||||
//live variables [arg -> blocks with usages]
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> live_in, live_out, live_inout;
|
||||
|
||||
bool addLive(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add, bool in);
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLive(bool in) const;
|
||||
bool removeLive(SAPFOR::Argument* to_remove, bool in);
|
||||
public:
|
||||
BasicBlock() { num = lastNumBlock++; }
|
||||
BasicBlock(IR_Block* item);
|
||||
BasicBlock(const BasicBlock& copyFrom);
|
||||
|
||||
void addInstructionBeforeInstruction(IR_Block* item, Instruction* istruction);
|
||||
void addInstructionInFront(IR_Block* item);
|
||||
void addInstruction(IR_Block* item);
|
||||
void addPrev(BasicBlock* prev_) { prev.push_back(prev_); }
|
||||
void addNext(BasicBlock* next_) { next.push_back(next_); }
|
||||
|
||||
int removePrev(BasicBlock* removed);
|
||||
int removeNext(BasicBlock* removed);
|
||||
|
||||
void replacePrevNext(const std::map<BasicBlock*, BasicBlock*>& oldToNew)
|
||||
{
|
||||
for (int z = 0; z < next.size(); ++z)
|
||||
{
|
||||
auto it = oldToNew.find(next[z]);
|
||||
if (it == oldToNew.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
next[z] = it->second;
|
||||
}
|
||||
|
||||
for (int z = 0; z < prev.size(); ++z)
|
||||
{
|
||||
auto it = oldToNew.find(prev[z]);
|
||||
if (it == oldToNew.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
prev[z] = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
int getNumber() const { return num; }
|
||||
const std::vector<IR_Block*>& getInstructions() const { return instructions; }
|
||||
const std::vector<BasicBlock*>& getNext() const { return next; }
|
||||
const std::vector<BasicBlock*>& getPrev() const { return prev; }
|
||||
|
||||
/*
|
||||
* FOR LIVE ANALYSIS
|
||||
*/
|
||||
bool addLiveIn(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, true); };
|
||||
bool addLiveOut(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, false); };
|
||||
|
||||
bool removeLiveIn(SAPFOR::Argument* to_remove) { return removeLive(to_remove, true); };
|
||||
bool removeLiveOut(SAPFOR::Argument* to_remove) { return removeLive(to_remove, false); };
|
||||
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLiveIn() const { return getLive(true); };
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLiveOut() const { return getLive(false); };
|
||||
void compressLives();
|
||||
|
||||
/*
|
||||
* FOR REACHING DEFINITIONS
|
||||
*/
|
||||
void setRD_In(const std::map<Argument*, std::set<int>>& inSet) { RD_in = inSet; }
|
||||
void setRD_Out(const std::map<Argument*, std::set<int>>& outSet) { RD_out = outSet; }
|
||||
const std::map<Argument*, std::set<int>>& getRD_In() const { return RD_in; }
|
||||
const std::map<Argument*, std::set<int>>& getRD_Out() const { return RD_out; }
|
||||
std::map<Argument*, std::set<int>>& getModRD_In() { return RD_in; }
|
||||
std::map<Argument*, std::set<int>>& getModRD_Out() { return RD_out; }
|
||||
|
||||
~BasicBlock();
|
||||
};
|
||||
|
||||
struct CFG_Settings
|
||||
{
|
||||
bool atLeastOneIterInLoop = false;
|
||||
bool withRD = true;
|
||||
bool withRegisters = false;
|
||||
bool withSPF = false;
|
||||
bool withDVM = false;
|
||||
bool withCallsInBlocks = false; // separate each F_CALL to own BasicBlock
|
||||
bool withCallFrom = true;
|
||||
|
||||
explicit CFG_Settings(int) { }
|
||||
|
||||
explicit CFG_Settings(bool atLeastOneIterInLoop = false, bool withRD = true, bool withRegisters = false,
|
||||
bool withDVM = false, bool withSPF = false, bool withCallsInBlocks = false, bool withCallFrom = true) :
|
||||
atLeastOneIterInLoop(atLeastOneIterInLoop), withRD(withRD), withRegisters(withRegisters), withDVM(withDVM), withSPF(withSPF),
|
||||
withCallsInBlocks(withCallsInBlocks), withCallFrom(withCallFrom)
|
||||
{ }
|
||||
};
|
||||
}
|
||||
|
||||
std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> buildCFG(const std::map<std::string, CommonBlock*>& commonBlocks, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, const SAPFOR::CFG_Settings settings);
|
||||
std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> buildCFGforCurrentFunc(SgStatement* stmt, SAPFOR::CFG_Settings settings, const std::map<std::string, CommonBlock*>& commonBlocks, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
|
||||
|
||||
std::vector<std::pair<const Variable*, CommonBlock*>> getCommonsByFunction(SgFile* file, SgStatement* function, const std::map<std::string, CommonBlock*>& commonBlocks);
|
||||
std::vector<SAPFOR::IR_Block*> getAllIR(const std::vector<SAPFOR::BasicBlock*>& blocks);
|
||||
void dumpCFG(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& blocks, bool withRD);
|
||||
std::vector<std::set<FuncInfo*>> groupByCallDependencies(const std::map<FuncInfo*, std::set<FuncInfo*>>& callDeps, std::vector<std::set<FuncInfo*>>& scc);
|
||||
|
||||
template<typename T>
|
||||
bool intersectAndAdd(std::set<T>& s1, const std::set<T>& s2);
|
||||
|
||||
void buildGenKillForCFG(const std::vector<SAPFOR::BasicBlock*>& CFG,
|
||||
const std::map<std::string, FuncInfo*>& funcByName,
|
||||
const std::map<FuncInfo*, std::map<SAPFOR::Argument*, std::set<int>>>& outForFunc,
|
||||
std::map<SAPFOR::BasicBlock*, std::map<SAPFOR::Argument*, std::set<int>>>& gen,
|
||||
std::map<SAPFOR::BasicBlock*, std::map<SAPFOR::Argument*, std::set<int>>>& kill,
|
||||
std::map<SAPFOR::Instruction*, std::map<SAPFOR::Argument*, std::set<int>>>* genForIR,
|
||||
std::map<SAPFOR::Instruction*, std::map<SAPFOR::Argument*, std::set<int>>>* killForIR,
|
||||
std::map<SAPFOR::BasicBlock*, std::set<SAPFOR::Argument*>>& notInitedGlobals,
|
||||
const SAPFOR::CFG_Settings settings);
|
||||
|
||||
static inline void deleteCFG(std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& cfg)
|
||||
{
|
||||
for (auto& byFunc : cfg)
|
||||
{
|
||||
for (auto& block : byFunc.second)
|
||||
delete block;
|
||||
byFunc.second.clear();
|
||||
}
|
||||
cfg.clear();
|
||||
}
|
||||
21
Sapfor/_src/CFGraph/DataFlow/backward_data_flow.h
Normal file
21
Sapfor/_src/CFGraph/DataFlow/backward_data_flow.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "data_flow.h"
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../../Utils/SgUtils.h"
|
||||
#include "../CFGraph.h"
|
||||
#include "../IR.h"
|
||||
|
||||
template <class NodeType>
|
||||
class BackwardDataFlowAnalysis : public DataFlowAnalysis<NodeType>
|
||||
{
|
||||
std::vector<SAPFOR::BasicBlock*> reorderSequence(const std::vector<SAPFOR::BasicBlock*>& blocks,
|
||||
const std::set<SAPFOR::BasicBlock*> back_edge_sources);
|
||||
public:
|
||||
void fit(const std::vector<SAPFOR::BasicBlock*>& blocks);
|
||||
};
|
||||
|
||||
#include "backward_data_flow_impl.h"
|
||||
103
Sapfor/_src/CFGraph/DataFlow/backward_data_flow_impl.h
Normal file
103
Sapfor/_src/CFGraph/DataFlow/backward_data_flow_impl.h
Normal file
@@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
#include "backward_data_flow.h"
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../../Utils/SgUtils.h"
|
||||
#include "../CFGraph.h"
|
||||
#include "../IR.h"
|
||||
#include "../RD_subst.h"
|
||||
|
||||
/* Note: this file should be included in backward_data_flow.h to provide template definitions */
|
||||
|
||||
// minimizes the number of blocks beween the ends of back edges
|
||||
template <class NodeType>
|
||||
std::vector<SAPFOR::BasicBlock*>
|
||||
BackwardDataFlowAnalysis<NodeType>::reorderSequence(const std::vector<SAPFOR::BasicBlock*>& blocks,
|
||||
const std::set<SAPFOR::BasicBlock*> back_edge_sources)
|
||||
{
|
||||
std::vector<SAPFOR::BasicBlock*> res = { };
|
||||
|
||||
auto blocks_end = blocks.rend();
|
||||
for (auto it = blocks.rbegin(); it < blocks_end; it++)
|
||||
{
|
||||
SAPFOR::BasicBlock* curr = *it;
|
||||
auto res_end = res.end();
|
||||
auto inserter = res.begin();
|
||||
if (back_edge_sources.count(curr) == 0)
|
||||
{
|
||||
auto curr_next_begin = curr->getNext().begin();
|
||||
auto curr_next_end = curr->getNext().end();
|
||||
while (inserter < res_end && std::find(curr_next_begin, curr_next_end, *inserter) == curr_next_end)
|
||||
inserter++;
|
||||
}
|
||||
|
||||
res.insert(inserter, curr);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <class NodeType>
|
||||
void BackwardDataFlowAnalysis<NodeType>::fit(const std::vector<SAPFOR::BasicBlock*>& blocks)
|
||||
{
|
||||
std::set<std::pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>> back_edges = {};
|
||||
|
||||
bool returned = false;
|
||||
std::map<SAPFOR::BasicBlock*, std::set<SAPFOR::BasicBlock*>> back_edges_by_src;
|
||||
|
||||
auto blocks_sorted = sortCfgNodes(blocks, &back_edges);
|
||||
|
||||
std::set<SAPFOR::BasicBlock*> back_edge_sources;
|
||||
|
||||
for (auto& edge : back_edges)
|
||||
{
|
||||
back_edges_by_src[edge.first].insert(edge.second);
|
||||
back_edge_sources.insert(edge.first);
|
||||
}
|
||||
|
||||
back_edges.clear();
|
||||
|
||||
blocks_sorted = reorderSequence(blocks_sorted, back_edge_sources);
|
||||
back_edge_sources.clear();
|
||||
|
||||
std::reverse(blocks_sorted.begin(), blocks_sorted.end());
|
||||
|
||||
this->nodes.clear();
|
||||
std::map<SAPFOR::BasicBlock*, NodeType*> node_by_block;
|
||||
|
||||
for (auto block : blocks_sorted)
|
||||
{
|
||||
NodeType* node = this->createNode(block);
|
||||
this->nodes.push_back(node);
|
||||
node_by_block[block] = node;
|
||||
}
|
||||
|
||||
int nodes_size = this->nodes.size();
|
||||
|
||||
for (int i = 0; i < nodes_size; i++)
|
||||
{
|
||||
NodeType* node = this->nodes[i];
|
||||
|
||||
auto back_edges_by_src_it = back_edges_by_src.find(node->getBlock());
|
||||
if (back_edges_by_src_it != back_edges_by_src.end())
|
||||
{
|
||||
// This node is a source for back edge
|
||||
for (auto dest : back_edges_by_src_it->second)
|
||||
{
|
||||
auto node_by_block_it = node_by_block.find(dest);
|
||||
if (node_by_block_it != node_by_block.end())
|
||||
node_by_block_it->second->getRollback().insert(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto next : node->getBlock()->getNext())
|
||||
{
|
||||
auto node_by_block_it = node_by_block.find(next);
|
||||
if (node_by_block_it != node_by_block.end())
|
||||
node->getPrevBlocks().insert(node_by_block_it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
68
Sapfor/_src/CFGraph/DataFlow/data_flow.h
Normal file
68
Sapfor/_src/CFGraph/DataFlow/data_flow.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
#include<vector>
|
||||
#include<set>
|
||||
|
||||
#include "../../Utils/SgUtils.h"
|
||||
#include "../CFGraph.h"
|
||||
#include "../IR.h"
|
||||
|
||||
enum class DATA_FLOW_UPD_STATUS { NO_CHANGE = 0, PROPAGATED, GENERATED };
|
||||
|
||||
template <class DataType>
|
||||
class DataFlowAnalysisNode {
|
||||
static const int CNT_NOTINIT = 0;
|
||||
|
||||
int in_cnt = CNT_NOTINIT, out_cnt = CNT_NOTINIT;
|
||||
|
||||
std::set<int> rollback;
|
||||
|
||||
std::set<DataFlowAnalysisNode<DataType>*> prev_blocks;
|
||||
|
||||
SAPFOR::BasicBlock* bb;
|
||||
public:
|
||||
DataFlowAnalysisNode();
|
||||
|
||||
void doStep();
|
||||
|
||||
virtual DataType getIn() = 0;
|
||||
virtual DataType getOut() = 0;
|
||||
|
||||
virtual bool addIn(const DataType& data) = 0;
|
||||
virtual bool addOut(const DataType& data) = 0;
|
||||
|
||||
virtual bool updateState() { return false; }
|
||||
virtual DATA_FLOW_UPD_STATUS forwardData(const DataType& data) = 0;
|
||||
|
||||
bool newerThan(const DataFlowAnalysisNode<DataType>* block) const { return out_cnt > block->in_cnt; }
|
||||
|
||||
int getInCnt() { return in_cnt; }
|
||||
int getOutCnt() { return out_cnt; }
|
||||
|
||||
void setInCnt(int cnt) { in_cnt = cnt; }
|
||||
void setOutCnt(int cnt) { out_cnt = cnt; }
|
||||
static int getStartCounter() { return CNT_NOTINIT; }
|
||||
|
||||
std::set<int>& getRollback() { return rollback; }
|
||||
|
||||
std::set<DataFlowAnalysisNode<DataType>*>& getPrevBlocks() { return prev_blocks; }
|
||||
|
||||
SAPFOR::BasicBlock* getBlock() { return bb; }
|
||||
void setBlock(SAPFOR::BasicBlock* b) { bb = b; }
|
||||
};
|
||||
|
||||
template <class NodeType>
|
||||
class DataFlowAnalysis {
|
||||
protected:
|
||||
std::vector<NodeType*> nodes;
|
||||
|
||||
virtual NodeType* createNode(SAPFOR::BasicBlock* block) = 0;
|
||||
public:
|
||||
virtual void fit(const std::vector<SAPFOR::BasicBlock*>& blocks) = 0;
|
||||
void analyze();
|
||||
|
||||
const std::vector<NodeType*>& getNodes() { return nodes; }
|
||||
|
||||
~DataFlowAnalysis();
|
||||
};
|
||||
|
||||
#include "data_flow_impl.h"
|
||||
112
Sapfor/_src/CFGraph/DataFlow/data_flow_impl.h
Normal file
112
Sapfor/_src/CFGraph/DataFlow/data_flow_impl.h
Normal file
@@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
#include "data_flow.h"
|
||||
|
||||
#include<vector>
|
||||
#include<set>
|
||||
|
||||
#include "../../Utils/SgUtils.h"
|
||||
#include "../CFGraph.h"
|
||||
#include "../IR.h"
|
||||
|
||||
/* Note: this file should be included in data_flow.h to provide template definitions */
|
||||
|
||||
/* definitions for DataFlowAnalysisNode class */
|
||||
|
||||
template <class DataType>
|
||||
const int DataFlowAnalysisNode<DataType>::CNT_NOTINIT;
|
||||
|
||||
template <class DataType>
|
||||
DataFlowAnalysisNode<DataType>::DataFlowAnalysisNode()
|
||||
{
|
||||
getRollback() = {};
|
||||
prev_blocks = {};
|
||||
}
|
||||
|
||||
template <class DataType>
|
||||
void DataFlowAnalysisNode<DataType>::doStep()
|
||||
{
|
||||
int in_max_cnt = CNT_NOTINIT, out_max_cnt = CNT_NOTINIT;
|
||||
|
||||
bool uniq_change = updateState();
|
||||
for (auto next : prev_blocks)
|
||||
{
|
||||
if (in_cnt < next->out_cnt)
|
||||
{
|
||||
if (next->out_cnt > in_max_cnt)
|
||||
in_max_cnt = next->out_cnt;
|
||||
|
||||
const auto& byOut = next->getOut();
|
||||
bool inserted = addIn( byOut);
|
||||
|
||||
if (inserted)
|
||||
{
|
||||
auto status = forwardData(byOut);
|
||||
inserted = status != DATA_FLOW_UPD_STATUS::NO_CHANGE;
|
||||
|
||||
if (inserted && next->out_cnt > out_max_cnt)
|
||||
out_max_cnt = next->out_cnt;
|
||||
|
||||
uniq_change |= status == DATA_FLOW_UPD_STATUS::GENERATED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uniq_change |= (out_cnt == CNT_NOTINIT);
|
||||
|
||||
if (out_max_cnt != CNT_NOTINIT)
|
||||
out_cnt = out_max_cnt;
|
||||
|
||||
if (in_max_cnt != CNT_NOTINIT)
|
||||
in_cnt = in_max_cnt;
|
||||
|
||||
// TODO: fix counter overflow
|
||||
if (uniq_change)
|
||||
{
|
||||
out_cnt++;
|
||||
in_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* definitions for DataFlowAnalysis class */
|
||||
|
||||
template <class NodeType>
|
||||
void DataFlowAnalysis<NodeType>::analyze()
|
||||
{
|
||||
auto curr = 0;
|
||||
auto stop = nodes.size();
|
||||
|
||||
while (curr != stop)
|
||||
{
|
||||
auto curr_bb = nodes[curr];
|
||||
curr_bb->doStep();
|
||||
|
||||
const auto& jumps = curr_bb->getRollback();
|
||||
if (jumps.size() != 0)
|
||||
{
|
||||
bool jump = false;
|
||||
for (const auto& jump_to : jumps)
|
||||
{
|
||||
if (curr_bb->newerThan(nodes[jump_to]))
|
||||
{
|
||||
jump = true;
|
||||
curr = jump_to;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (jump)
|
||||
continue;
|
||||
}
|
||||
|
||||
curr++;
|
||||
}
|
||||
}
|
||||
|
||||
template <class NodeType>
|
||||
DataFlowAnalysis<NodeType>::~DataFlowAnalysis()
|
||||
{
|
||||
for (NodeType* node : nodes)
|
||||
delete node;
|
||||
|
||||
nodes.clear();
|
||||
}
|
||||
1752
Sapfor/_src/CFGraph/IR.cpp
Normal file
1752
Sapfor/_src/CFGraph/IR.cpp
Normal file
File diff suppressed because it is too large
Load Diff
349
Sapfor/_src/CFGraph/IR.h
Normal file
349
Sapfor/_src/CFGraph/IR.h
Normal file
@@ -0,0 +1,349 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "CFGraph.h"
|
||||
#include "../Utils/CommonBlock.h"
|
||||
|
||||
namespace SAPFOR
|
||||
{
|
||||
struct CFG_Settings;
|
||||
|
||||
enum class CFG_OP { NONE, ASSIGN, POINTER_ASS, LOAD, STORE, REC_REF_LOAD, REC_REF_STORE, REF, PARAM, IO_PARAM, RANGE, ENTRY, REC_REF,
|
||||
ADD, MULT, DIV, SUBT, UN_ADD, UN_MINUS, POW, CONCAT, CAST,
|
||||
JUMP, JUMP_IF,
|
||||
GE, LE, GT, LT, EQ, NEQV, EQV, EMPTY, OR, AND, NOT,
|
||||
F_CALL, EXIT,
|
||||
DVM_DIR, SPF_DIR };
|
||||
|
||||
enum class CFG_ARG_TYPE { NONE, REG, VAR, ARRAY, CONST, FUNC, LAB, INSTR, CONST_STR, RECORD, CONSTR_REF };
|
||||
enum class CFG_MEM_TYPE { NONE_, COMMON_, SAVE_, LOCAL_, MODULE_, FUNC_RES_, FUNC_PARAM_, FILED_ };
|
||||
|
||||
static std::vector<std::string> CFG_OP_S = { "--", " = ", " => ", "LOAD ", "STORE ", "LOAD_REF ", "STORE_REF ", "REF ", "PARAM ", "IO_PARAM ", "RANGE ", "ENTRY ", "->",
|
||||
" + ", " * ", " / ", " - ", " + ", "-", " ** ", " // ", "CAST ",
|
||||
"GOTO ", "IF_FALSE ",
|
||||
" >= ", " <= ", " > " , " < ", " == ", " != ", " eqv ", "CONTINUE", " || ", " && ", " ! ",
|
||||
"F_CALL ", "EXIT ",
|
||||
" ", " " };
|
||||
|
||||
class Argument
|
||||
{
|
||||
static int lastNumArg;
|
||||
private:
|
||||
int number;
|
||||
|
||||
CFG_ARG_TYPE type;
|
||||
CFG_MEM_TYPE mType;
|
||||
std::string value;
|
||||
public:
|
||||
Argument() : number(lastNumArg++), type(CFG_ARG_TYPE::NONE), value(""), mType(CFG_MEM_TYPE::NONE_) { }
|
||||
Argument(CFG_ARG_TYPE type, CFG_MEM_TYPE mType) : number(lastNumArg++), type(type), mType(mType), value("") { }
|
||||
Argument(CFG_ARG_TYPE type, CFG_MEM_TYPE mType, const std::string& value) : number(lastNumArg++), type(type), mType(mType), value(value) { }
|
||||
Argument(CFG_ARG_TYPE type, CFG_MEM_TYPE mType, const std::string& value, int num) : number(num), type(type), mType(mType), value(value) { }
|
||||
Argument(CFG_ARG_TYPE type, const std::string& value) : number(lastNumArg++), type(type), mType(CFG_MEM_TYPE::NONE_), value(value)
|
||||
{
|
||||
if (type != CFG_ARG_TYPE::INSTR && type == CFG_ARG_TYPE::LAB &&
|
||||
type != CFG_ARG_TYPE::NONE && type != CFG_ARG_TYPE::FUNC)
|
||||
{
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
void setType(CFG_ARG_TYPE newType) { type = newType; }
|
||||
CFG_ARG_TYPE getType() const { return type; }
|
||||
|
||||
void setMemType(CFG_MEM_TYPE newType) { mType = newType; }
|
||||
CFG_MEM_TYPE getMemType() const { return mType; }
|
||||
|
||||
bool isMemGlobal() const
|
||||
{
|
||||
if (mType == CFG_MEM_TYPE::COMMON_ ||
|
||||
mType == CFG_MEM_TYPE::MODULE_ ||
|
||||
mType == CFG_MEM_TYPE::SAVE_)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isParameter() const
|
||||
{
|
||||
if (mType == CFG_MEM_TYPE::FUNC_RES_ ||
|
||||
mType == CFG_MEM_TYPE::FUNC_PARAM_)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void setValue(const std::string& newValue) { value = newValue; }
|
||||
const std::string getValue() const
|
||||
{
|
||||
if (type == CFG_ARG_TYPE::CONST_STR || type == CFG_ARG_TYPE::CONSTR_REF)
|
||||
return "'" + value + "'";
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
int getNumber() const { return number; }
|
||||
|
||||
std::string getMemTypeStr() const
|
||||
{
|
||||
if (mType == CFG_MEM_TYPE::NONE_)
|
||||
return "none";
|
||||
else if (mType == CFG_MEM_TYPE::COMMON_)
|
||||
return "common";
|
||||
else if (mType == CFG_MEM_TYPE::LOCAL_)
|
||||
return "local";
|
||||
else if (mType == CFG_MEM_TYPE::MODULE_)
|
||||
return "module";
|
||||
else if (mType == CFG_MEM_TYPE::FUNC_RES_)
|
||||
return "func_res";
|
||||
else if (mType == CFG_MEM_TYPE::FUNC_PARAM_)
|
||||
return "func_par";
|
||||
else if (mType == CFG_MEM_TYPE::SAVE_)
|
||||
return "save";
|
||||
else if (mType == CFG_MEM_TYPE::FILED_)
|
||||
return "filed";
|
||||
else
|
||||
return "error";
|
||||
}
|
||||
|
||||
~Argument() { }
|
||||
};
|
||||
|
||||
class Instruction
|
||||
{
|
||||
static int lastNumInstr;
|
||||
private:
|
||||
int number;
|
||||
|
||||
CFG_OP operation;
|
||||
Argument* arg1;
|
||||
Argument* arg2;
|
||||
Argument* result;
|
||||
|
||||
SgStatement* st = NULL;
|
||||
SgExpression* ex = NULL;
|
||||
|
||||
std::string getArgValue(Argument* arg) const
|
||||
{
|
||||
if (arg == NULL)
|
||||
return "";
|
||||
return arg->getValue();
|
||||
}
|
||||
public:
|
||||
|
||||
Instruction() : number(lastNumInstr++), operation(CFG_OP::NONE), arg1(NULL), arg2(NULL), result(NULL) { }
|
||||
Instruction(CFG_OP op, Argument* arg1 = NULL, Argument* arg2 = NULL, Argument* res = NULL, SgStatement* st = NULL, SgExpression* ex = NULL) :
|
||||
number(lastNumInstr++), operation(op), arg1(arg1), arg2(arg2), result(res), st(st), ex(ex) { }
|
||||
|
||||
Instruction(CFG_OP op, SgStatement* st) : number(lastNumInstr++), operation(op), arg1(NULL), arg2(NULL), result(NULL), st(st) { }
|
||||
|
||||
Instruction(CFG_OP op, int num, Argument* arg1 = NULL, Argument* arg2 = NULL, Argument* res = NULL, SgStatement* st = NULL, SgExpression* ex = NULL) :
|
||||
number(num), operation(op), arg1(arg1), arg2(arg2), result(res), st(st), ex(ex) { }
|
||||
|
||||
void setOperation(CFG_OP op) { operation = op; }
|
||||
CFG_OP getOperation() const { return operation; }
|
||||
|
||||
Argument* getArg1() const { return arg1; }
|
||||
Argument* getArg2() const { return arg2; }
|
||||
Argument* getResult() const { return result; }
|
||||
|
||||
void setArg1(Argument* arg) { arg1 = arg; }
|
||||
void setArg2(Argument* arg) { arg2 = arg; }
|
||||
void setResult(Argument* arg) { result = arg; }
|
||||
|
||||
int getNumber() const { return number; }
|
||||
void shiftNumber(int add) { number += add; }
|
||||
|
||||
SgStatement* getOperator() const { return st; }
|
||||
void setOperator(SgStatement* st_) { st = st_; }
|
||||
|
||||
SgExpression* getExpression() const { return ex; }
|
||||
|
||||
int getLine() const { return st ? st->lineNumber() : -1; }
|
||||
|
||||
bool isAccess() const
|
||||
{
|
||||
std::set<CFG_OP> accessOps = { CFG_OP::LOAD , CFG_OP::STORE, CFG_OP::REC_REF_LOAD, CFG_OP::REC_REF_STORE };
|
||||
return accessOps.find(operation) != accessOps.end();
|
||||
}
|
||||
|
||||
bool isArith() const
|
||||
{
|
||||
std::set<CFG_OP> arithOps = { CFG_OP::ADD, CFG_OP::MULT, CFG_OP::DIV, CFG_OP::SUBT, CFG_OP::UN_ADD, CFG_OP::UN_MINUS, CFG_OP::POW, CFG_OP::CONCAT };
|
||||
//CFG_OP::CAST, CFG_OP::GE, CFG_OP::LE, CFG_OP::GT, CFG_OP::LT, CFG_OP::EQ, CFG_OP::NEQV, CFG_OP::EQV, CFG_OP::OR, CFG_OP::AND, CFG_OP::NOT };
|
||||
|
||||
return (arithOps.find(operation) != arithOps.end()) || isIntirinsicCall();
|
||||
}
|
||||
|
||||
bool isIntirinsicCall() const
|
||||
{
|
||||
if (operation == CFG_OP::F_CALL)
|
||||
{
|
||||
if (ex)
|
||||
{
|
||||
if (isIntrinsicFunctionName(ex->symbol()->identifier()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int getNextInstrNum() { return lastNumInstr; }
|
||||
static void shiftNextInstrNum(int byNum) { lastNumInstr += byNum; }
|
||||
|
||||
std::string dump()
|
||||
{
|
||||
std::string res = "";
|
||||
|
||||
std::string resultVal = getArgValue(result);
|
||||
std::string arg1Val = getArgValue(arg1);
|
||||
std::string arg2Val = getArgValue(arg2);
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case CFG_OP::ADD:
|
||||
case CFG_OP::MULT:
|
||||
case CFG_OP::DIV:
|
||||
case CFG_OP::SUBT:
|
||||
case CFG_OP::GE:
|
||||
case CFG_OP::LE:
|
||||
case CFG_OP::GT:
|
||||
case CFG_OP::LT:
|
||||
case CFG_OP::EQ:
|
||||
case CFG_OP::NEQV:
|
||||
case CFG_OP::EQV:
|
||||
case CFG_OP::OR:
|
||||
case CFG_OP::AND:
|
||||
case CFG_OP::POW:
|
||||
case CFG_OP::CONCAT:
|
||||
res = resultVal + " = " + arg1Val + CFG_OP_S[(int)operation] + arg2Val;
|
||||
break;
|
||||
case CFG_OP::NOT:
|
||||
case CFG_OP::UN_MINUS:
|
||||
case CFG_OP::UN_ADD:
|
||||
res = resultVal + " = " + CFG_OP_S[(int)operation] + arg1Val;
|
||||
break;
|
||||
case CFG_OP::POINTER_ASS:
|
||||
res = arg1Val + CFG_OP_S[(int)operation] + resultVal;
|
||||
break;
|
||||
case CFG_OP::ASSIGN:
|
||||
if (arg2)
|
||||
res = resultVal + CFG_OP_S[(int)operation] + arg1Val + " [" + arg2Val + "]";
|
||||
else
|
||||
res = resultVal + CFG_OP_S[(int)operation] + arg1Val;
|
||||
break;
|
||||
case CFG_OP::JUMP:
|
||||
case CFG_OP::ENTRY:
|
||||
res = CFG_OP_S[(int)operation] + arg1Val;
|
||||
break;
|
||||
case CFG_OP::JUMP_IF:
|
||||
res = CFG_OP_S[(int)operation] + arg1Val + " then goto " + arg2Val;
|
||||
break;
|
||||
case CFG_OP::EMPTY:
|
||||
res = CFG_OP_S[(int)operation];
|
||||
break;
|
||||
case CFG_OP::LOAD:
|
||||
case CFG_OP::REC_REF_LOAD:
|
||||
res = CFG_OP_S[(int)operation] + resultVal + " " + arg1Val + (arg2 ? (" " + arg2Val) : "");
|
||||
break;
|
||||
case CFG_OP::REC_REF_STORE:
|
||||
case CFG_OP::STORE:
|
||||
res = CFG_OP_S[(int)operation] + arg1Val + (arg2 ? (" " + arg2Val) : "") + " " + resultVal;
|
||||
break;
|
||||
case CFG_OP::REC_REF:
|
||||
res = "LOAD " + resultVal + " " + arg1Val + CFG_OP_S[(int)operation] + arg2Val;
|
||||
break;
|
||||
case CFG_OP::REF:
|
||||
case CFG_OP::PARAM:
|
||||
case CFG_OP::IO_PARAM:
|
||||
res = CFG_OP_S[(int)operation] + arg1Val;
|
||||
break;
|
||||
case CFG_OP::CAST:
|
||||
res = resultVal + " = " + CFG_OP_S[(int)operation] + arg1Val;
|
||||
break;
|
||||
case CFG_OP::F_CALL:
|
||||
if (result)
|
||||
res = resultVal + " = " + CFG_OP_S[(int)operation] + arg1Val + " " + arg2Val;
|
||||
else
|
||||
res = CFG_OP_S[(int)operation] + arg1Val + " " + arg2Val;
|
||||
break;
|
||||
case CFG_OP::RANGE:
|
||||
res = CFG_OP_S[(int)operation] + "[ ";
|
||||
if (arg1)
|
||||
res += arg1Val;
|
||||
res += " : ";
|
||||
if (arg2)
|
||||
res += arg2Val;
|
||||
res += " : ";
|
||||
if (result)
|
||||
res += resultVal;
|
||||
res += " ]";
|
||||
break;
|
||||
case CFG_OP::DVM_DIR:
|
||||
case CFG_OP::SPF_DIR:
|
||||
res = (st != NULL) ? std::string(st->unparse()) : "NULL";
|
||||
break;
|
||||
default:
|
||||
res = CFG_OP_S[(int)operation];
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
class IR_Block
|
||||
{
|
||||
private:
|
||||
Instruction* current;
|
||||
Instruction* jumpTo;
|
||||
|
||||
BasicBlock* bblock;
|
||||
bool header;
|
||||
public:
|
||||
IR_Block(Instruction* instr) : current(instr), jumpTo(NULL), bblock(NULL), header(false) { }
|
||||
IR_Block(const IR_Block& copyFrom)
|
||||
{
|
||||
current = new Instruction(*copyFrom.getInstruction());
|
||||
bblock = NULL;
|
||||
//need to replace with actual IR
|
||||
jumpTo = copyFrom.getJump();
|
||||
header = false;
|
||||
}
|
||||
|
||||
Instruction* getInstruction() const { return current; }
|
||||
Instruction* getJump() const { return jumpTo; }
|
||||
BasicBlock* getBasicBlock() const { return bblock; }
|
||||
int getNumber() const { return current->getNumber(); }
|
||||
|
||||
void setJump(Instruction* instr) { jumpTo = instr; }
|
||||
void setBasicBlock(BasicBlock* newBlock) { bblock = newBlock; }
|
||||
|
||||
void setHeader() { header = true; }
|
||||
bool isHeader() const { return header; }
|
||||
|
||||
int getLine() const { return current->getLine(); }
|
||||
|
||||
~IR_Block() { delete current; }
|
||||
};
|
||||
|
||||
class BasicBlock;
|
||||
}
|
||||
|
||||
std::string createName(const std::vector<std::pair<const Variable*, CommonBlock*>>& commonVars, const FuncInfo* func,
|
||||
SgSymbol* s, SgStatement* scope, SAPFOR::CFG_MEM_TYPE& mType);
|
||||
std::string getNameByArg(SAPFOR::Argument* arg);
|
||||
SgSymbol* getSybolByArg(SAPFOR::Argument* arg);
|
||||
SAPFOR::Argument* createArg(const std::string& fullName, const std::string& name, SAPFOR::CFG_MEM_TYPE mType);
|
||||
|
||||
std::vector<SAPFOR::IR_Block*> buildIR(SgStatement* function, const FuncInfo* func, const std::vector<std::pair<const Variable*, CommonBlock*>>& commonVars, const SAPFOR::CFG_Settings settings);
|
||||
SAPFOR::Instruction* getInstructionByNumber(const std::vector<SAPFOR::IR_Block*>& blocks, int num);
|
||||
std::pair<SAPFOR::Instruction*, SAPFOR::BasicBlock*> getInstructionAndBlockByNumber(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph, int num);
|
||||
std::pair<SAPFOR::Instruction*, SAPFOR::BasicBlock*> getInstructionAndBlockByStatement(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph, SgStatement* stmt);
|
||||
int getParamIndex(SAPFOR::Argument* func_param, int max_index);
|
||||
|
||||
void testIR(std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> fullIR);
|
||||
588
Sapfor/_src/CFGraph/IRSSAForm.cpp
Normal file
588
Sapfor/_src/CFGraph/IRSSAForm.cpp
Normal file
@@ -0,0 +1,588 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../Utils/CommonBlock.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
#include "../ExpressionTransform/expr_transform.h"
|
||||
|
||||
#include "dvm.h"
|
||||
#include "IR.h"
|
||||
#include "CFGraph.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace SAPFOR;
|
||||
|
||||
typedef SAPFOR::BasicBlock BBlock;
|
||||
typedef SAPFOR::Argument BArgument;
|
||||
|
||||
static void printBlock(BBlock* block) {
|
||||
cout << "block - " << block->getNumber() << endl;
|
||||
cout << "next -";
|
||||
for (auto i : block->getNext())
|
||||
{
|
||||
cout << " " << i->getNumber();
|
||||
}
|
||||
cout << endl << "prev -";
|
||||
for (auto i : block->getPrev())
|
||||
{
|
||||
cout << " " << i->getNumber();
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
for (auto i : block->getInstructions())
|
||||
{
|
||||
string resValue = "";
|
||||
string arg1Value = "";
|
||||
string arg2Value = "";
|
||||
if (i->getInstruction()->getResult() != nullptr && i->getInstruction()->getResult()->getType() == CFG_ARG_TYPE::VAR) {
|
||||
resValue = i->getInstruction()->getResult()->getValue();
|
||||
i->getInstruction()->getResult()->setValue(i->getInstruction()->getResult()->getValue() + to_string(i->getInstruction()->getResult()->getNumber()));
|
||||
}
|
||||
if (i->getInstruction()->getArg1() != nullptr && i->getInstruction()->getArg1()->getType() == CFG_ARG_TYPE::VAR) {
|
||||
arg1Value = i->getInstruction()->getArg1()->getValue();
|
||||
i->getInstruction()->getArg1()->setValue(i->getInstruction()->getArg1()->getValue() + to_string(i->getInstruction()->getArg1()->getNumber()));
|
||||
}
|
||||
if (i->getInstruction()->getArg2() != nullptr && i->getInstruction()->getArg2()->getType() == CFG_ARG_TYPE::VAR) {
|
||||
arg2Value = i->getInstruction()->getArg2()->getValue();
|
||||
i->getInstruction()->getArg2()->setValue(i->getInstruction()->getArg2()->getValue() + to_string(i->getInstruction()->getArg2()->getNumber()));
|
||||
}
|
||||
|
||||
cout << i->getNumber() << " " << i->getInstruction()->dump() << endl;// << (i->getInstruction()->getResult() != nullptr ? " 1 " : " 0 ") << (i->getInstruction()->getArg1() != nullptr ? "1 " : "0 ") << (i->getInstruction()->getArg2() != nullptr ? "1 " : "0 ") << endl;
|
||||
|
||||
/*if (i->getInstruction()->getResult() != nullptr) {
|
||||
cout << "num - " << i->getInstruction()->getResult()->getNumber() << endl;
|
||||
})*/
|
||||
|
||||
/*if (i->getInstruction()->getOperation() == CFG_OP::F_CALL) {
|
||||
cout << endl;
|
||||
cout << "arg1 - " << (i->getInstruction()->getArg1()->getType() == CFG_ARG_TYPE::FUNC ? "1" : "0") << "arg2 - " << (i->getInstruction()->getArg2()->getType() == CFG_ARG_TYPE::CONST ? "1" : "0") << "res - " << i->getInstruction()->getResult() << endl;
|
||||
}*/
|
||||
|
||||
if (i->getInstruction()->getResult() != nullptr && i->getInstruction()->getResult()->getType() == CFG_ARG_TYPE::VAR) {
|
||||
i->getInstruction()->getResult()->setValue(resValue);
|
||||
}
|
||||
if (i->getInstruction()->getArg1() != nullptr && i->getInstruction()->getArg1()->getType() == CFG_ARG_TYPE::VAR) {
|
||||
i->getInstruction()->getArg1()->setValue(arg1Value);
|
||||
}
|
||||
if (i->getInstruction()->getArg2() != nullptr && i->getInstruction()->getArg2()->getType() == CFG_ARG_TYPE::VAR) {
|
||||
i->getInstruction()->getArg2()->setValue(arg2Value);
|
||||
}
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
}
|
||||
template <typename T>
|
||||
static bool compareVectors(const vector<T>* vec1, const vector<T>* vec2) {
|
||||
if (vec1 == vec2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!vec1 || !vec2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<T> sortedVec1 = *vec1;
|
||||
vector<T> sortedVec2 = *vec2;
|
||||
|
||||
sort(sortedVec1.begin(), sortedVec1.end());
|
||||
sort(sortedVec2.begin(), sortedVec2.end());
|
||||
|
||||
return sortedVec1 == sortedVec2;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static vector<T>* getCommonElements(const vector<vector<T>>* vectors) {
|
||||
if (!vectors || vectors->empty()) {
|
||||
return new vector<T>(); // Return an empty vector if input is null or empty
|
||||
}
|
||||
|
||||
// Start with the first vector
|
||||
vector<T>* commonElements = new vector<T>((*vectors)[0]);
|
||||
|
||||
for (size_t i = 1; i < vectors->size(); ++i) {
|
||||
vector<T> tempCommon;
|
||||
|
||||
// Sort the current vector and common result for intersection
|
||||
vector<T> sortedVec = (*vectors)[i];
|
||||
sort(commonElements->begin(), commonElements->end());
|
||||
sort(sortedVec.begin(), sortedVec.end());
|
||||
|
||||
// Find the intersection
|
||||
set_intersection(
|
||||
commonElements->begin(), commonElements->end(),
|
||||
sortedVec.begin(), sortedVec.end(),
|
||||
back_inserter(tempCommon)
|
||||
);
|
||||
|
||||
// Update common result
|
||||
*commonElements = tempCommon;
|
||||
|
||||
// If no common elements left, break early
|
||||
if (commonElements->empty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return commonElements;
|
||||
}
|
||||
|
||||
|
||||
static map<BBlock*, vector<BBlock*>> findDominators(vector<BBlock*> blocks) {
|
||||
map<BBlock*, vector<BBlock*>> result;
|
||||
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
|
||||
for (auto currentBlock : blocks) {
|
||||
auto pred = currentBlock->getPrev();
|
||||
auto prevDominators = new vector<vector<BBlock*>>();
|
||||
|
||||
for (auto predBlock : pred)
|
||||
prevDominators->push_back(result.find(predBlock) != result.end() ? result[predBlock] : blocks);
|
||||
|
||||
auto currentBlockResult = getCommonElements(prevDominators);
|
||||
currentBlockResult->push_back(currentBlock);
|
||||
|
||||
if (result.find(currentBlock) == result.end() || !compareVectors(currentBlockResult, &result[currentBlock])) {
|
||||
result[currentBlock] = *currentBlockResult;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void RenumberBlocks(BBlock* current, int* n, map<int, int>* res, set<BBlock*>* visited) {
|
||||
if (visited->find(current) != visited->end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
visited->insert(current);
|
||||
|
||||
vector<BBlock*> nextBlocks = current->getNext();
|
||||
|
||||
sort(nextBlocks.begin(), nextBlocks.end(), [](BBlock* a, BBlock* b) {
|
||||
return a->getInstructions()[0]->getInstruction()->getOperator()->lineNumber() > b->getInstructions()[0]->getInstruction()->getOperator()->lineNumber();
|
||||
});
|
||||
|
||||
for (auto i : nextBlocks) {
|
||||
RenumberBlocks(i, n, res, visited);
|
||||
}
|
||||
|
||||
(*res)[current->getNumber()] = *n;
|
||||
*n -= 1;
|
||||
}
|
||||
|
||||
static map<BBlock*, vector<BBlock*>> findDominatorBorders(vector<BBlock*>& blocks, map<BBlock*, BBlock*>& iDominators) {
|
||||
map<BBlock*, vector<BBlock*>> result;
|
||||
|
||||
for (auto block : blocks) {
|
||||
result[block] = *(new vector<BBlock*>());
|
||||
}
|
||||
|
||||
for (auto block : blocks) {
|
||||
if (block->getPrev().size() > 1) {
|
||||
for (auto prev : block->getPrev()) {
|
||||
auto tmpBlock = prev;
|
||||
|
||||
while (tmpBlock != iDominators[block]) {
|
||||
result[tmpBlock].push_back(block);
|
||||
tmpBlock = iDominators[tmpBlock];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static BBlock* findImmediateDominatorsDfsHelper(BBlock* block, BBlock* currentBlock, BBlock* currentImmediateDominator, vector<BBlock*> &visited, map<BBlock*, vector<BBlock*>>& dominators) {
|
||||
if (block == currentBlock) {
|
||||
return currentImmediateDominator;
|
||||
}
|
||||
|
||||
if (find(visited.begin(), visited.end(), currentBlock) != visited.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
visited.push_back(currentBlock);
|
||||
|
||||
if (find(dominators[block].begin(), dominators[block].end(), currentBlock) != dominators[block].end()) {
|
||||
currentImmediateDominator = currentBlock;
|
||||
}
|
||||
|
||||
for (auto nextBlock : currentBlock->getNext()) {
|
||||
auto result = findImmediateDominatorsDfsHelper(block, nextBlock, currentImmediateDominator, visited, dominators);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static map<BBlock*, BBlock*> findImmediateDominators(map<BBlock*, vector<BBlock*>>& dominators, BBlock* fistBlock) {
|
||||
map<BBlock*, BBlock*> iDominators;
|
||||
|
||||
for (const auto& domPair : dominators) {
|
||||
BBlock* block = domPair.first;
|
||||
const vector<BBlock*>& domBlocks = domPair.second;
|
||||
vector<BBlock*> visited;
|
||||
|
||||
if (block == fistBlock) {
|
||||
continue;
|
||||
}
|
||||
|
||||
iDominators[block] = findImmediateDominatorsDfsHelper(block, fistBlock, fistBlock, visited, dominators);
|
||||
}
|
||||
|
||||
return iDominators;
|
||||
}
|
||||
|
||||
static vector<BArgument*> getDefForBlock(const BBlock& block) {
|
||||
vector<BArgument*> def;
|
||||
const auto& instructions = block.getInstructions();
|
||||
|
||||
for (const auto& irBlock : instructions) {
|
||||
if (irBlock) {
|
||||
Instruction* instr = irBlock->getInstruction();
|
||||
|
||||
if (instr) {
|
||||
BArgument* result = instr->getResult();
|
||||
if (result) {
|
||||
def.push_back(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
static pair<set<BArgument*>, map<BArgument*, set<BBlock*>>> getGlobalsAndVarBlocks(vector<BBlock*> blocks) {
|
||||
set<BArgument*> globals;
|
||||
map<BArgument*, set<BBlock*>> varBlocks;
|
||||
|
||||
for (auto block : blocks) {
|
||||
set<BArgument*> def;
|
||||
const auto& instructions = block->getInstructions();
|
||||
|
||||
for (const auto& irBlock : instructions) {
|
||||
if (irBlock) {
|
||||
Instruction* instr = irBlock->getInstruction();
|
||||
|
||||
if (instr) {
|
||||
auto arg1 = instr->getArg1();
|
||||
auto arg2 = instr->getArg2();
|
||||
auto res = instr->getResult();
|
||||
|
||||
if (arg1 && arg1->getType() == CFG_ARG_TYPE::VAR && find(def.begin(), def.end(), arg1) == def.end()) {
|
||||
globals.insert(arg1);
|
||||
}
|
||||
if (arg2 && arg2->getType() == CFG_ARG_TYPE::VAR && find(def.begin(), def.end(), arg2) == def.end()) {
|
||||
globals.insert(arg2);
|
||||
}
|
||||
|
||||
if (res && res->getType() == CFG_ARG_TYPE::VAR) {
|
||||
def.insert(res);
|
||||
varBlocks[res].insert(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return make_pair(globals, varBlocks);
|
||||
}
|
||||
|
||||
static vector<BBlock*> getBlocksWithFiFunctions(vector<BBlock*> blocks, set<BArgument*> globals, map<BArgument*, set<BBlock*>> varBlocks, map<BBlock*, vector<BBlock*>> dominatorBorders) {
|
||||
vector<BBlock*> blocksWithFiFunctions;
|
||||
auto fiFunc = new BArgument(CFG_ARG_TYPE::FUNC, CFG_MEM_TYPE::NONE_, "FI_FUNCTION");
|
||||
auto paramCount = new BArgument(CFG_ARG_TYPE::CONST, CFG_MEM_TYPE::LOCAL_, "0");
|
||||
|
||||
for (auto var : globals) {
|
||||
auto worklist = varBlocks[var];
|
||||
set<BBlock*> hasFiFunction;
|
||||
|
||||
while (!worklist.empty()) {
|
||||
auto block = *worklist.begin();
|
||||
worklist.erase(block);
|
||||
|
||||
for (auto dfBlock : dominatorBorders[block]) {
|
||||
if (hasFiFunction.find(dfBlock) == hasFiFunction.end()) {
|
||||
hasFiFunction.insert(dfBlock);
|
||||
|
||||
Instruction* phiInstruction = new Instruction(CFG_OP::F_CALL, fiFunc, paramCount, var);
|
||||
|
||||
//cout << "insert fi functio9n in " << dfBlock->getNumber() << " with var " << var->getValue() << endl;
|
||||
|
||||
IR_Block* phiBlock = new IR_Block(phiInstruction);
|
||||
dfBlock->addInstructionInFront(phiBlock);
|
||||
|
||||
blocksWithFiFunctions.push_back(dfBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blocksWithFiFunctions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
string ToString(CFG_ARG_TYPE type) {
|
||||
switch (type) {
|
||||
case CFG_ARG_TYPE::NONE: return "NONE";
|
||||
case CFG_ARG_TYPE::REG: return "REG";
|
||||
case CFG_ARG_TYPE::VAR: return "VAR";
|
||||
case CFG_ARG_TYPE::ARRAY: return "ARRAY";
|
||||
case CFG_ARG_TYPE::CONST: return "CONST";
|
||||
case CFG_ARG_TYPE::FUNC: return "FUNC";
|
||||
case CFG_ARG_TYPE::LAB: return "LAB";
|
||||
case CFG_ARG_TYPE::INSTR: return "INSTR";
|
||||
case CFG_ARG_TYPE::CONST_STR: return "CONST_STR";
|
||||
case CFG_ARG_TYPE::RECORD: return "RECORD";
|
||||
case CFG_ARG_TYPE::CONSTR_REF: return "CONSTR_REF";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void restoreConnections(const vector<BBlock*>& originalBlocks, vector<BBlock*>& copiedBlocks) {
|
||||
// Создаем отображение оригинальных блоков в их копии
|
||||
map<BBlock*, BBlock*> blockMapping;
|
||||
for (size_t i = 0; i < originalBlocks.size(); ++i) {
|
||||
blockMapping[originalBlocks[i]] = copiedBlocks[i];
|
||||
}
|
||||
|
||||
// Восстанавливаем связи между копиями
|
||||
for (size_t i = 0; i < originalBlocks.size(); ++i) {
|
||||
BBlock* originalBlock = originalBlocks[i];
|
||||
BBlock* copiedBlock = copiedBlocks[i];
|
||||
|
||||
for (auto j : copiedBlock->getPrev()) {
|
||||
copiedBlock->removePrev(j);
|
||||
}
|
||||
for (auto j : copiedBlock->getNext()) {
|
||||
copiedBlock->removeNext(j);
|
||||
}
|
||||
|
||||
// Восстанавливаем связи succ (следующих блоков)
|
||||
for (auto* succ : originalBlock->getNext()) {
|
||||
copiedBlock->addNext(blockMapping[succ]);
|
||||
}
|
||||
|
||||
// Восстанавливаем связи prev (предыдущих блоков)
|
||||
for (auto* prev : originalBlock->getPrev()) {
|
||||
copiedBlock->addPrev(blockMapping[prev]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BArgument* NewName(BArgument* var, map<string, int>& counter, map<string, stack<BArgument*>>& stack) {
|
||||
int index = counter[var->getValue()];
|
||||
counter[var->getValue()]++;
|
||||
|
||||
BArgument* newName = new BArgument(var->getType(), var->getMemType(), var->getValue(), index + 1);
|
||||
stack[var->getValue()].push(newName);
|
||||
return newName;
|
||||
}
|
||||
|
||||
void RenameFiFunctionResultVar(BBlock* block, map<string, int>& counter, map<string, stack<BArgument*>>& stack) {
|
||||
for (auto irBlock : block->getInstructions()) {
|
||||
auto instruction = irBlock->getInstruction();
|
||||
if (instruction->getOperation() == CFG_OP::F_CALL && instruction->getArg1() != nullptr && instruction->getArg1()->getValue() == "FI_FUNCTION" && instruction->getResult() != nullptr) {
|
||||
instruction->setResult(NewName(instruction->getResult(), counter, stack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenameInstructionVars(BBlock* block, map<string, int>& counter, map<string, stack<BArgument*>>& stack) {
|
||||
for (auto irBlock : block->getInstructions()) {
|
||||
auto instruction = irBlock->getInstruction();
|
||||
|
||||
if (instruction->getArg1() != nullptr && instruction->getArg1()->getType() == CFG_ARG_TYPE::VAR) {
|
||||
instruction->setArg1(stack[instruction->getArg1()->getValue()].top());
|
||||
}
|
||||
|
||||
if (instruction->getArg2() != nullptr && instruction->getArg2()->getType() == CFG_ARG_TYPE::VAR) {
|
||||
instruction->setArg2(stack[instruction->getArg2()->getValue()].top());
|
||||
}
|
||||
|
||||
if (instruction->getResult() != nullptr && instruction->getResult()->getType() == CFG_ARG_TYPE::VAR) {
|
||||
instruction->setResult(NewName(instruction->getResult(), counter, stack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenameFiFunctionArgsVar(BBlock* block, map<string, stack<BArgument*>>& stack) {
|
||||
cout << "test" << endl;
|
||||
auto size = block->getInstructions().size();
|
||||
for (auto i = 0; i < size; i++) {
|
||||
auto irBlock = block->getInstructions()[i];
|
||||
auto instruction = irBlock->getInstruction();
|
||||
if (instruction->getOperation() == CFG_OP::F_CALL && instruction->getArg1() != nullptr && instruction->getArg1()->getValue() == "FI_FUNCTION" && instruction->getResult() != nullptr) {
|
||||
//cout << "test" << endl;
|
||||
|
||||
auto paramInstruction = new Instruction(CFG_OP::PARAM, stack[instruction->getResult()->getValue()].top());
|
||||
block->addInstructionBeforeInstruction(new IR_Block(paramInstruction), instruction);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<BBlock*> findBlocksWithValue(map<BBlock*, BBlock*>& iDominators, BBlock* x) {
|
||||
vector<BBlock*> result;
|
||||
|
||||
// Проходим по всем элементам map
|
||||
for (auto& pair : iDominators) {
|
||||
// Если значение равно x, добавляем ключ в результат
|
||||
if (pair.second == x) {
|
||||
result.push_back(pair.first);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void RenameIR(BBlock* block, map<BBlock*, BBlock*>& iDominators, map<string, int>& counter, map<string, stack<BArgument*>>& stack) {
|
||||
|
||||
RenameFiFunctionResultVar(block, counter, stack);
|
||||
|
||||
RenameInstructionVars(block, counter, stack);
|
||||
|
||||
for (auto* successor : block->getNext()) {
|
||||
RenameFiFunctionArgsVar(successor, stack);
|
||||
}
|
||||
|
||||
for (auto* child : findBlocksWithValue(iDominators, block)) {
|
||||
cout << "sec" << endl;
|
||||
RenameIR(child, iDominators, counter, stack);
|
||||
}
|
||||
|
||||
for (auto& irBlock : block->getInstructions()) {
|
||||
auto instruction = irBlock->getInstruction();
|
||||
if (instruction->getResult() != nullptr && instruction->getResult()->getType() == CFG_ARG_TYPE::VAR) {
|
||||
string varName = instruction->getResult()->getValue();
|
||||
stack[varName].pop();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& irBlock : block->getInstructions()) {
|
||||
auto instruction = irBlock->getInstruction();
|
||||
if (instruction->getOperation() == CFG_OP::F_CALL && instruction->getArg1() != nullptr && instruction->getArg1()->getValue() == "FI_FUNCTION" && instruction->getResult() != nullptr) {
|
||||
string varName = instruction->getResult()->getValue();
|
||||
stack[varName].pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map<FuncInfo*, vector<BBlock*>> buildIRSSAForm(map<FuncInfo*, vector<BBlock*>> fullIR) {
|
||||
|
||||
map<FuncInfo*, vector<BBlock*>> result;
|
||||
|
||||
for (auto item : fullIR) {
|
||||
auto funcinfo = item.first;
|
||||
auto funcIRConst = item.second;
|
||||
|
||||
vector<BBlock*> funcIR;
|
||||
vector<BBlock*> funcResult;
|
||||
|
||||
for (auto i : funcIRConst) {
|
||||
funcIR.push_back(new BBlock(*i));
|
||||
}
|
||||
restoreConnections(funcIRConst, funcIR);
|
||||
|
||||
for (auto i : funcIR) {
|
||||
//printBlock(i);
|
||||
}
|
||||
|
||||
auto dominators = findDominators(funcIR);
|
||||
|
||||
/*cout << endl << endl << endl << "DOMINATORS" << endl << endl << endl;
|
||||
|
||||
for (auto i : dominators) {
|
||||
cout << "block - " << i.first->getNumber() << endl;
|
||||
for (auto j : i.second) {
|
||||
cout << "dominators - " << j->getNumber() << endl;
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
}*/
|
||||
|
||||
auto iDominators = findImmediateDominators(dominators, funcIR[0]);
|
||||
|
||||
/*for (auto i : iDominators) {
|
||||
cout << "block - " << i.first->getNumber() << endl;
|
||||
cout << "Idominators - " << i.second->getNumber() << endl;
|
||||
cout << endl;
|
||||
}
|
||||
*/
|
||||
auto dominatorBorders = findDominatorBorders(funcIR, iDominators);
|
||||
|
||||
|
||||
/*for (auto i : dominatorBorders) {
|
||||
cout << "block - " << i.first->getNumber() << endl;
|
||||
for (auto j : i.second) {
|
||||
cout << "border - " << j->getNumber() << endl;
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
}*/
|
||||
|
||||
|
||||
auto globalsAndVarBlocks = getGlobalsAndVarBlocks(funcIR);
|
||||
auto globals = globalsAndVarBlocks.first;
|
||||
auto varBlocks = globalsAndVarBlocks.second;
|
||||
|
||||
/*for (auto i : globals) {
|
||||
cout << i->getValue() << " " << ToString(i->getType()) << " " << i->getNumber() << endl;
|
||||
|
||||
}
|
||||
cout << endl;
|
||||
for (auto i : varBlocks) {
|
||||
cout << i.first->getValue() << " - ";
|
||||
for (auto j : i.second) {
|
||||
cout << j->getNumber() << ", ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
cout << endl;
|
||||
*/
|
||||
|
||||
funcResult = getBlocksWithFiFunctions(funcIR, globals, varBlocks, dominatorBorders);
|
||||
|
||||
map<string, int> count;
|
||||
map<string, stack<BArgument*>> varStack;
|
||||
|
||||
for (auto var : globals) {
|
||||
count[var->getValue()] = 0;
|
||||
|
||||
stack<BArgument*> tmp;
|
||||
varStack[var->getValue()] = tmp;
|
||||
}
|
||||
|
||||
RenameIR(funcIR[0], iDominators, count, varStack);
|
||||
|
||||
for (auto i : funcIR) {
|
||||
printBlock(i);
|
||||
}
|
||||
cout << endl << endl << endl << endl << endl;
|
||||
for (auto i : funcIRConst) {
|
||||
printBlock(i);
|
||||
}
|
||||
|
||||
|
||||
result[funcinfo] = funcResult;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
6
Sapfor/_src/CFGraph/IRSSAForm.h
Normal file
6
Sapfor/_src/CFGraph/IRSSAForm.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "CFGraph.h"
|
||||
#include "IR.h"
|
||||
|
||||
std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> buildIRSSAForm(std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>> fullIR);
|
||||
1872
Sapfor/_src/CFGraph/RD_subst.cpp
Normal file
1872
Sapfor/_src/CFGraph/RD_subst.cpp
Normal file
File diff suppressed because it is too large
Load Diff
40
Sapfor/_src/CFGraph/RD_subst.h
Normal file
40
Sapfor/_src/CFGraph/RD_subst.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include<unordered_map>
|
||||
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../Utils/CommonBlock.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
|
||||
#include "CFGraph.h"
|
||||
#include "IR.h"
|
||||
|
||||
inline bool hasStoreStructure(SAPFOR::CFG_OP type)
|
||||
{
|
||||
return (type == SAPFOR::CFG_OP::STORE) ||
|
||||
(type == SAPFOR::CFG_OP::REC_REF_STORE) ||
|
||||
(type == SAPFOR::CFG_OP::POINTER_ASS);
|
||||
}
|
||||
|
||||
const std::map<std::string, SgSymbol*>& getCommonArgsByFunc(FuncInfo* func, std::map<FuncInfo*, std::map<std::string, SgSymbol*>>& cache,
|
||||
const std::vector<std::pair<const Variable*, CommonBlock*>>& commonVars,
|
||||
std::unordered_map<SgSymbol*, std::string>& globals_cache,
|
||||
std::unordered_map<SgSymbol*, std::string>& locals_cache);
|
||||
|
||||
std::vector<SAPFOR::BasicBlock*> sortCfgNodes(const std::vector<SAPFOR::BasicBlock*>& blocks,
|
||||
std::set<std::pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>>* ignored_edges = NULL);
|
||||
|
||||
const std::string& getArgNameBySymbol(const std::vector<std::pair<const Variable*, CommonBlock*>>& commonVars,
|
||||
const FuncInfo* func, SgSymbol* s, std::unordered_map<SgSymbol*, std::string>& globals_cache,
|
||||
std::unordered_map<SgSymbol*, std::string>& locals_cache);
|
||||
|
||||
// main functions of SUBST_EXPR_RD pass
|
||||
void buildSubstitutions(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project, const std::map<std::string, CommonBlock*>& commonBlocks, SgProject* project);
|
||||
void performRDSubst(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project, const std::map<std::string, CommonBlock*>& commonBlocks, SgProject* project);
|
||||
void revertSubstitutions();
|
||||
|
||||
void cancelRevertionForStatement(std::string filename, SgStatement* stmt, int i);
|
||||
|
||||
/*void destroyReplacementsInFiles();
|
||||
void destroyOldExpressionsInFile();
|
||||
void destroyAllSubstitutionsData();*/
|
||||
761
Sapfor/_src/CFGraph/live_variable_analysis.cpp
Normal file
761
Sapfor/_src/CFGraph/live_variable_analysis.cpp
Normal file
@@ -0,0 +1,761 @@
|
||||
#include "live_variable_analysis.h"
|
||||
#include "RD_subst.h"
|
||||
#include "DataFlow/backward_data_flow.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
|
||||
using std::string;
|
||||
using std::pair;
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using std::set;
|
||||
using std::unordered_map;
|
||||
using std::list;
|
||||
|
||||
using LIVE_VARIABLES::LiveDeadVarsForCall;
|
||||
|
||||
namespace SAPFOR
|
||||
{
|
||||
bool BasicBlock::addLive(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& to_add, bool in) {
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& current_set = (in ? live_in : live_out);
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& opposite_set = (!in ? live_in : live_out);
|
||||
|
||||
bool inserted = false;
|
||||
for (const auto& byNew : to_add)
|
||||
{
|
||||
const vector<SAPFOR::BasicBlock*>& add_in_live = byNew.second;
|
||||
vector<SAPFOR::BasicBlock*> new_in_live = {};
|
||||
|
||||
auto current_set_iter = current_set.find(byNew.first);
|
||||
|
||||
if (current_set_iter == current_set.end())
|
||||
new_in_live = add_in_live;
|
||||
else
|
||||
std::set_difference(add_in_live.begin(), add_in_live.end(), current_set_iter->second.begin(), current_set_iter->second.end(), std::inserter(new_in_live, new_in_live.begin()));
|
||||
|
||||
auto opposite_set_iter = opposite_set.find(byNew.first);
|
||||
auto both_set_iter = live_inout.find(byNew.first);
|
||||
|
||||
if (new_in_live.size() != 0)
|
||||
{
|
||||
inserted = true;
|
||||
|
||||
bool current_set_has_argument = current_set_iter != current_set.end();
|
||||
bool opposite_set_has_argument = opposite_set_iter != opposite_set.end();
|
||||
bool both_set_has_argument = both_set_iter != live_inout.end();
|
||||
|
||||
for (SAPFOR::BasicBlock* bb : new_in_live)
|
||||
{
|
||||
bool insert_to_both = false;
|
||||
if (opposite_set_has_argument)
|
||||
{
|
||||
auto& usages_from_opposite = opposite_set_iter->second;
|
||||
auto find_bb_from_opposite = std::lower_bound(usages_from_opposite.begin(), usages_from_opposite.end(), bb);
|
||||
|
||||
if (find_bb_from_opposite != usages_from_opposite.end() && *find_bb_from_opposite == bb)
|
||||
{
|
||||
insert_to_both = true;
|
||||
usages_from_opposite.erase(find_bb_from_opposite);
|
||||
|
||||
if (usages_from_opposite.size() == 0) {
|
||||
opposite_set.erase(opposite_set_iter);
|
||||
opposite_set_has_argument = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (insert_to_both)
|
||||
{
|
||||
if (!both_set_has_argument) {
|
||||
both_set_iter = live_inout.insert({ byNew.first, {} }).first;
|
||||
both_set_has_argument = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!current_set_has_argument) {
|
||||
current_set_iter = current_set.insert({ byNew.first, {} }).first;
|
||||
current_set_has_argument = true;
|
||||
}
|
||||
}
|
||||
|
||||
vector<SAPFOR::BasicBlock*>& dest = insert_to_both ? both_set_iter->second : current_set_iter->second;
|
||||
|
||||
auto find_bb_from_dest = std::lower_bound(dest.begin(), dest.end(), bb);
|
||||
|
||||
if (find_bb_from_dest == dest.end() || *find_bb_from_dest != bb)
|
||||
dest.insert(find_bb_from_dest, bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return inserted;
|
||||
}
|
||||
|
||||
bool BasicBlock::removeLive(SAPFOR::Argument* to_remove, bool in)
|
||||
{
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& current_set = (in ? live_in : live_out);
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& opposite_set = (!in ? live_in : live_out);
|
||||
|
||||
bool removed = false;
|
||||
|
||||
removed |= (current_set.erase(to_remove) != 0);
|
||||
|
||||
auto it = live_inout.find(to_remove);
|
||||
|
||||
if (it != live_inout.end())
|
||||
{
|
||||
auto& dest = opposite_set[to_remove];
|
||||
for (SAPFOR::BasicBlock* bb : it->second)
|
||||
{
|
||||
auto find_bb_from_dest = std::lower_bound(dest.begin(), dest.end(), bb);
|
||||
|
||||
if (find_bb_from_dest == dest.end() || *find_bb_from_dest != bb)
|
||||
dest.insert(find_bb_from_dest, bb);
|
||||
}
|
||||
|
||||
live_inout.erase(to_remove);
|
||||
removed = true;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> BasicBlock::getLive(bool in) const {
|
||||
auto& current_set = in ? live_in : live_out;
|
||||
|
||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> res;
|
||||
|
||||
for (auto& by_source : { current_set, live_inout })
|
||||
{
|
||||
for (auto& by_pair : by_source)
|
||||
{
|
||||
auto& dest = res[by_pair.first];
|
||||
auto dest_copy = dest;
|
||||
|
||||
dest.resize(dest_copy.size() + by_pair.second.size());
|
||||
|
||||
set_union(dest_copy.begin(), dest_copy.end(), by_pair.second.begin(), by_pair.second.end(), dest.begin());
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void BasicBlock::compressLives() {
|
||||
for (auto& bySrc : { &live_in, &live_out, &live_inout })
|
||||
for (auto& byArg : *bySrc)
|
||||
byArg.second.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
|
||||
bool LiveDeadVarsForCall::tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
|
||||
{
|
||||
if (b == block || dest.find(block) == dest.end())
|
||||
{
|
||||
dest.insert(b);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
LiveDeadVarsForCall::LiveDeadVarsForCall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
|
||||
{
|
||||
block = b;
|
||||
func = f;
|
||||
|
||||
int param_size = p.size();
|
||||
params = vector<SAPFOR::Argument*>(param_size, NULL);
|
||||
|
||||
for (int i = 0; i < param_size; i++)
|
||||
if (f->funcParams.isArgOut(i))
|
||||
params[i] = p[i];
|
||||
}
|
||||
|
||||
void LiveDeadVarsForCall::make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b)
|
||||
{
|
||||
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
|
||||
{
|
||||
if (commons_dead_after.find(arg) == commons_dead_after.end())
|
||||
tryInsert(commons_live_after[arg], b);
|
||||
}
|
||||
|
||||
auto it = find(params.begin(), params.end(), arg);
|
||||
if (it != params.end())
|
||||
{
|
||||
int idx = it - params.begin();
|
||||
if (dead_after.find(idx) == dead_after.end())
|
||||
tryInsert(live_after[idx], b);
|
||||
}
|
||||
}
|
||||
|
||||
void LiveDeadVarsForCall::make_dead(SAPFOR::Argument* arg)
|
||||
{
|
||||
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
|
||||
{
|
||||
if (commons_live_after.find(arg) == commons_live_after.end())
|
||||
commons_dead_after.insert(arg);
|
||||
}
|
||||
|
||||
auto it = find(params.begin(), params.end(), arg);
|
||||
if (it != params.end())
|
||||
{
|
||||
int idx = it - params.begin();
|
||||
if (live_after.find(idx) == live_after.end())
|
||||
dead_after.insert(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void LiveDeadVarsForCall::updateFromOut()
|
||||
{
|
||||
for (const auto& p : block->getLiveOut())
|
||||
for (auto b : p.second)
|
||||
make_live(p.first, b);
|
||||
}
|
||||
|
||||
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
|
||||
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead);
|
||||
|
||||
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
|
||||
const map<string, FuncInfo*>& funcByName, bool interprocedural);
|
||||
|
||||
class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>> {
|
||||
private:
|
||||
set<SAPFOR::Argument*> live, dead;
|
||||
public:
|
||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getIn()
|
||||
{
|
||||
return getBlock()->getLiveOut();
|
||||
}
|
||||
|
||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getOut()
|
||||
{
|
||||
return getBlock()->getLiveIn();
|
||||
}
|
||||
|
||||
bool addIn(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
||||
{
|
||||
return getBlock()->addLiveOut(data);
|
||||
}
|
||||
|
||||
bool addOut(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
||||
{
|
||||
return getBlock()->addLiveIn(data);
|
||||
}
|
||||
|
||||
DATA_FLOW_UPD_STATUS forwardData(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
||||
{
|
||||
bool inserted = false;
|
||||
|
||||
for (const auto& byArg : data)
|
||||
if (live.find(byArg.first) == live.end() && dead.find(byArg.first) == dead.end())
|
||||
inserted |= getBlock()->addLiveIn({ byArg });
|
||||
|
||||
return inserted ? DATA_FLOW_UPD_STATUS::PROPAGATED : DATA_FLOW_UPD_STATUS::NO_CHANGE;
|
||||
}
|
||||
|
||||
LiveVarAnalysisNode(SAPFOR::BasicBlock* block, vector<SAPFOR::Argument*>& formal_parameters,
|
||||
vector<LiveDeadVarsForCall>& fcalls, const map<string, FuncInfo*>& funcByName)
|
||||
{
|
||||
setBlock(block);
|
||||
|
||||
buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName, true);
|
||||
|
||||
for (SAPFOR::Argument* arg : live)
|
||||
getBlock()->addLiveIn({ { arg, { getBlock() } } });
|
||||
}
|
||||
};
|
||||
|
||||
class LiveVarAnalysis : public BackwardDataFlowAnalysis<LiveVarAnalysisNode> {
|
||||
protected:
|
||||
vector<SAPFOR::Argument*>& formal_parameters;
|
||||
vector<LiveDeadVarsForCall>& fcalls;
|
||||
const map<string, FuncInfo*>& funcByName;
|
||||
|
||||
LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override {
|
||||
return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName);
|
||||
}
|
||||
public:
|
||||
LiveVarAnalysis(vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
|
||||
const map<string, FuncInfo*>& funcByName) : formal_parameters(formal_parameters), fcalls(fcalls), funcByName(funcByName)
|
||||
{ }
|
||||
};
|
||||
|
||||
void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
||||
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
|
||||
vector<SAPFOR::Argument*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
|
||||
bool& last_stack_op,
|
||||
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
|
||||
{
|
||||
for (auto arg : { instr->getArg1(), instr->getArg2(), instr->getResult() })
|
||||
if (arg && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_)
|
||||
formal_parameters[getParamIndex(arg, formal_parameters.size())] = arg;
|
||||
|
||||
last_stack_op = false;
|
||||
SAPFOR::Argument* res_arg = NULL;
|
||||
|
||||
static const set<SAPFOR::CFG_OP> skip = { SAPFOR::CFG_OP::ENTRY };
|
||||
SAPFOR::CFG_OP instr_operation = instr->getOperation();
|
||||
if (instr_operation == SAPFOR::CFG_OP::F_CALL ||
|
||||
instr_operation == SAPFOR::CFG_OP::STORE ||
|
||||
instr_operation == SAPFOR::CFG_OP::LOAD)
|
||||
{
|
||||
res_arg = (instr_operation == SAPFOR::CFG_OP::STORE ? instr->getArg1() : instr->getResult());
|
||||
if(instr_operation != SAPFOR::CFG_OP::F_CALL)
|
||||
use.insert(instr_operation != SAPFOR::CFG_OP::STORE ? instr->getArg1() : instr->getResult());
|
||||
|
||||
arg_stack_size = stoi(instr->getArg2()->getValue());
|
||||
|
||||
arg_stack.clear();
|
||||
arg_stack.resize(arg_stack_size);
|
||||
|
||||
arg_stack_index = arg_stack_size - 1;
|
||||
|
||||
if(instr_operation == SAPFOR::CFG_OP::F_CALL)
|
||||
fName = instr->getArg1()->getValue();
|
||||
}
|
||||
else if (hasStoreStructure(instr_operation))
|
||||
{
|
||||
res_arg = instr->getArg1();
|
||||
set<SAPFOR::Argument*> instr_args = { instr->getResult(), instr->getArg2() };
|
||||
use.insert(instr_args.begin(), instr_args.end());
|
||||
}
|
||||
else if (instr_operation == SAPFOR::CFG_OP::PARAM || instr_operation == SAPFOR::CFG_OP::REF)
|
||||
{
|
||||
arg_stack[arg_stack_index--] = instr->getArg1();
|
||||
}
|
||||
else if (skip.find(instr_operation) == skip.end())
|
||||
{
|
||||
//default
|
||||
res_arg = instr->getResult();
|
||||
std::set<SAPFOR::Argument*> intr_args = { instr->getArg1(), instr->getArg2() };
|
||||
use.insert(intr_args.begin(), intr_args.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
//skip
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg_stack_index < 0) {
|
||||
if(instr_operation == SAPFOR::CFG_OP::PARAM || instr_operation == SAPFOR::CFG_OP::F_CALL)
|
||||
{
|
||||
auto func_it = funcByName.find(fName);
|
||||
if (interprocedural && func_it != funcByName.end())
|
||||
{
|
||||
fcalls.push_back(LiveDeadVarsForCall(func_it->second, block, arg_stack));
|
||||
|
||||
auto r_it = fcalls.rbegin();
|
||||
auto r_end = fcalls.rend();
|
||||
|
||||
for (auto e : def)
|
||||
r_it->make_dead(e);
|
||||
|
||||
for (auto e : use)
|
||||
r_it->make_live(e, block);
|
||||
}
|
||||
|
||||
set<SAPFOR::Argument*> make_live, make_dead;
|
||||
if (fName == "_READ")
|
||||
def.insert(arg_stack.begin(), arg_stack.end());
|
||||
else if (interprocedural && getLiveDead(arg_stack, fName, make_live, make_dead))
|
||||
{
|
||||
use.insert(make_live.begin(), make_live.end());
|
||||
def.insert(make_dead.begin(), make_dead.end());
|
||||
}
|
||||
else if (func_it != funcByName.end())
|
||||
{
|
||||
int arg_num = arg_stack.size();
|
||||
for (int i = 0; i < arg_num; i++)
|
||||
{
|
||||
if(func_it->second->funcParams.isArgOut(i))
|
||||
def.insert(arg_stack[i]);
|
||||
|
||||
if (func_it->second->funcParams.isArgIn(i))
|
||||
use.insert(arg_stack[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
use.insert(arg_stack.begin(), arg_stack.end());
|
||||
|
||||
fName = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
use.insert(arg_stack.begin(), arg_stack.end());
|
||||
}
|
||||
|
||||
arg_stack_index = 0;
|
||||
arg_stack_size = 0;
|
||||
|
||||
arg_stack.clear();
|
||||
|
||||
last_stack_op = true;
|
||||
}
|
||||
|
||||
if (res_arg)
|
||||
def.insert(res_arg);
|
||||
}
|
||||
|
||||
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
||||
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
|
||||
vector<SAPFOR::Argument*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
|
||||
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
|
||||
{
|
||||
set<SAPFOR::Argument*> res, args;
|
||||
bool last_stack_op;
|
||||
getUseDefForInstruction(block, instr,
|
||||
args, res,
|
||||
formal_parameters, fcalls,
|
||||
arg_stack, arg_stack_index, arg_stack_size,
|
||||
last_stack_op,
|
||||
fName, funcByName,
|
||||
interprocedural
|
||||
);
|
||||
|
||||
for (auto e : res)
|
||||
{
|
||||
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
{
|
||||
def.insert(e);
|
||||
use.erase(e);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto e : args)
|
||||
{
|
||||
if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
{
|
||||
use.insert(e);
|
||||
def.erase(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Build use and def sets of block. Result are stored in use and def
|
||||
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& fcalls,
|
||||
const map<string, FuncInfo*>& funcByName, bool interprocedural)
|
||||
{
|
||||
vector<SAPFOR::Argument*> arg_stack;
|
||||
int arg_stack_index = 0, arg_stack_size = 0;
|
||||
string fName;
|
||||
|
||||
const auto& instructions = block->getInstructions();
|
||||
auto ir_block_it = instructions.rbegin(), ir_block_end = instructions.rend();
|
||||
|
||||
for (; ir_block_it != ir_block_end; ir_block_it++)
|
||||
{
|
||||
updateUseDefForInstruction(block, (*ir_block_it)->getInstruction(),
|
||||
use, def,
|
||||
formal_parameters, fcalls,
|
||||
arg_stack, arg_stack_index, arg_stack_size,
|
||||
fName, funcByName,
|
||||
interprocedural
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// prints info about live variables
|
||||
void doDumpLive(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project)
|
||||
{
|
||||
for (const auto& byFunc : CFGraph_for_project)
|
||||
{
|
||||
__spf_print(1, "============================================\n");
|
||||
__spf_print(1, "Live variables '%s' function\n", byFunc.first->funcName.c_str());
|
||||
__spf_print(1, "============================================\n");
|
||||
for (auto byBB : byFunc.second)
|
||||
{
|
||||
__spf_print(1, "[BB %d]\n", byBB->getNumber());
|
||||
__spf_print(1, " IN:\n");
|
||||
for (const auto& live : byBB->getLiveIn())
|
||||
{
|
||||
__spf_print(1, " %s:", live.first->getValue().c_str());
|
||||
for (auto use : live.second)
|
||||
__spf_print(1, " %d", use->getNumber());
|
||||
__spf_print(1, "\n");
|
||||
}
|
||||
|
||||
__spf_print(1, " OUT:\n");
|
||||
for (const auto& live : byBB->getLiveOut())
|
||||
{
|
||||
__spf_print(1, " %s:", live.first->getValue().c_str());
|
||||
for (auto use : live.second)
|
||||
__spf_print(1, " %d", use->getNumber());
|
||||
__spf_print(1, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sets for the next function
|
||||
static map<string, pair<set<int>, set<SAPFOR::Argument*>>> live_by_func, dead_by_func;
|
||||
|
||||
// fill sets of arguments wich becomes live or dead after call of this function
|
||||
static void fillLiveDeadArgs(const FuncInfo* func, const vector<SAPFOR::BasicBlock*>& blocks)
|
||||
{
|
||||
if (blocks.size() == 0)
|
||||
return;
|
||||
|
||||
SAPFOR::BasicBlock* entrypoint = NULL;
|
||||
int entrypoint_first_instr = 0;
|
||||
set<SAPFOR::BasicBlock*> exits = {};
|
||||
|
||||
for (auto block : blocks)
|
||||
{
|
||||
if (block->getNext().size() == 0)
|
||||
exits.insert(block);
|
||||
|
||||
if (block->getInstructions().front()->isHeader())
|
||||
{
|
||||
if (!entrypoint || block->getInstructions()[0]->getNumber() < entrypoint_first_instr)
|
||||
{
|
||||
entrypoint_first_instr = block->getInstructions()[0]->getNumber();
|
||||
entrypoint = block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!entrypoint)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
set<int> live, dead;
|
||||
set<SAPFOR::Argument*> common_live, common_dead;
|
||||
|
||||
for (const auto& arg : entrypoint->getLiveIn())
|
||||
{
|
||||
switch (arg.first->getMemType())
|
||||
{
|
||||
case SAPFOR::CFG_MEM_TYPE::COMMON_:
|
||||
case SAPFOR::CFG_MEM_TYPE::MODULE_:
|
||||
common_live.insert(arg.first);
|
||||
break;
|
||||
case SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_:
|
||||
{
|
||||
int num = getParamIndex(arg.first, func->funcParams.countOfPars);
|
||||
if (func->funcParams.isArgIn(num))
|
||||
live.insert(num);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto byExit : exits)
|
||||
{
|
||||
for (const auto& byRd : byExit->getRD_Out())
|
||||
{
|
||||
auto out_arg = byRd.first;
|
||||
if (!(byRd.second.size() == 1 && *(byRd.second.begin()) < 0))
|
||||
{
|
||||
switch (out_arg->getMemType())
|
||||
{
|
||||
case SAPFOR::CFG_MEM_TYPE::COMMON_:
|
||||
case SAPFOR::CFG_MEM_TYPE::MODULE_:
|
||||
if (!common_live.count(out_arg))
|
||||
common_dead.insert(out_arg);
|
||||
break;
|
||||
case SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_:
|
||||
{
|
||||
int num = getParamIndex(out_arg, func->funcParams.countOfPars);
|
||||
|
||||
if (!live.count(num) && func->funcParams.isArgOut(num))
|
||||
dead.insert(num);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
live_by_func[func->funcName] = { live, common_live };
|
||||
dead_by_func[func->funcName] = { dead, common_dead };
|
||||
}
|
||||
|
||||
// unite global arguments and actual parameters with given indexes for function
|
||||
// stores the result in the last argument
|
||||
bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params,
|
||||
const map<string, pair<set<int>, set<SAPFOR::Argument*>>>& params_and_globals,
|
||||
const string& func_name, set<SAPFOR::Argument*>& result)
|
||||
{
|
||||
auto globals_it = params_and_globals.find(func_name);
|
||||
|
||||
if (globals_it == params_and_globals.end())
|
||||
return false;
|
||||
|
||||
const auto& param_indexes = globals_it->second.first;
|
||||
const auto& globals = globals_it->second.second;
|
||||
|
||||
int params_size = params.size();
|
||||
|
||||
for (int idx : param_indexes)
|
||||
{
|
||||
if (idx < params_size) {
|
||||
if (params[idx] && params[idx]->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
result.insert(params[idx]);
|
||||
}
|
||||
else
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
result.insert(globals.begin(), globals.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
// fill sets of arguments wich becomes live or dead after call with parameters params
|
||||
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
|
||||
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead)
|
||||
{
|
||||
return joinGlobalsWithParameters(params, live_by_func, func_name, live) &&
|
||||
joinGlobalsWithParameters(params, dead_by_func, func_name, dead);
|
||||
}
|
||||
|
||||
// entrypoint for live variable analysis pass
|
||||
void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project)
|
||||
{
|
||||
/*
|
||||
Here we assume that there is no recursive (explicit or implicit) calls.
|
||||
So it is easy to process CALL instruction: just use live_in set of first block
|
||||
for this function (that has already been built).
|
||||
*/
|
||||
|
||||
map<FuncInfo*, set<FuncInfo*>> callDeps;
|
||||
map<string, FuncInfo*> funcByName;
|
||||
|
||||
for (auto& byFunc : CFGraph_for_project)
|
||||
{
|
||||
callDeps[byFunc.first].insert(byFunc.first->callsFromV.begin(), byFunc.first->callsFromV.end());
|
||||
funcByName[byFunc.first->funcName] = byFunc.first;
|
||||
}
|
||||
|
||||
vector<set<FuncInfo*>> scc;
|
||||
vector<set<FuncInfo*>> callLvls = groupByCallDependencies(callDeps, scc);
|
||||
|
||||
map<string, LiveVarAnalysis*> func_to_analysis_object;
|
||||
map<string, vector<SAPFOR::Argument*>> func_to_parameters;
|
||||
|
||||
list<vector<LiveDeadVarsForCall>> live_for_fcalls;
|
||||
|
||||
//TODO: take into account ssc structure
|
||||
// main stage
|
||||
for (auto& byLvl : callLvls)
|
||||
{
|
||||
live_for_fcalls.push_front({});
|
||||
auto& curr_fcalls = live_for_fcalls.front();
|
||||
|
||||
for (auto& byFunc : byLvl)
|
||||
{
|
||||
auto itCFG = CFGraph_for_project.find(byFunc);
|
||||
if (itCFG == CFGraph_for_project.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
|
||||
auto& params = func_to_parameters[byFunc->funcName] = vector<SAPFOR::Argument*>(byFunc->funcParams.countOfPars, NULL);
|
||||
|
||||
LiveVarAnalysis* analysis_object = (func_to_analysis_object[byFunc->funcName] = new LiveVarAnalysis(params, curr_fcalls, funcByName));
|
||||
analysis_object->fit(itCFG->second);
|
||||
analysis_object->analyze();
|
||||
|
||||
fillLiveDeadArgs(byFunc, itCFG->second);
|
||||
}
|
||||
}
|
||||
|
||||
// interprocedural analysis
|
||||
for (auto& calls_vector : live_for_fcalls)
|
||||
{
|
||||
map<FuncInfo*, LiveDeadVarsForCall> assembled_fcalls;
|
||||
for (auto& call : calls_vector)
|
||||
{
|
||||
call.updateFromOut();
|
||||
call.params.clear();
|
||||
call.commons_dead_after.clear();
|
||||
call.dead_after.clear();
|
||||
|
||||
auto it = assembled_fcalls.find(call.func);
|
||||
if (it == assembled_fcalls.end())
|
||||
it = assembled_fcalls.insert({ call.func, LiveDeadVarsForCall(call.func, call.block, {}) }).first;
|
||||
|
||||
for (const auto& p : call.live_after)
|
||||
it->second.live_after[p.first].insert(p.second.begin(), p.second.end());
|
||||
|
||||
for (const auto& p : call.commons_live_after)
|
||||
it->second.commons_live_after[p.first].insert(p.second.begin(), p.second.end());
|
||||
}
|
||||
|
||||
for (const auto& func : assembled_fcalls)
|
||||
{
|
||||
auto func_it = func_to_analysis_object.find(func.first->funcName);
|
||||
if (func_it == func_to_analysis_object.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
auto param_it = func_to_parameters.find(func.first->funcName);
|
||||
if (param_it == func_to_parameters.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
const vector<SAPFOR::Argument*>& params = param_it->second;
|
||||
auto params_begin = params.begin(), params_end = params.end();
|
||||
|
||||
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> live_after = func.second.commons_live_after;
|
||||
|
||||
for (auto curr = params_begin; curr < params_end; curr++)
|
||||
{
|
||||
if (*curr)
|
||||
{
|
||||
const auto& live_param_it = func.second.live_after.find(curr - params_begin);
|
||||
if (live_param_it != func.second.live_after.end())
|
||||
live_after[*curr].insert(live_param_it->second.begin(), live_param_it->second.end());
|
||||
}
|
||||
}
|
||||
|
||||
set<LiveVarAnalysisNode*> exits;
|
||||
int max_cnt = LiveVarAnalysisNode::getStartCounter();
|
||||
for (auto block : func_it->second->getNodes())
|
||||
{
|
||||
if (block->getBlock()->getNext().size() == 0)
|
||||
exits.insert(block);
|
||||
if (block->getInCnt() > max_cnt)
|
||||
max_cnt = block->getInCnt();
|
||||
}
|
||||
|
||||
max_cnt++;
|
||||
|
||||
for (auto exit : exits)
|
||||
{
|
||||
for (const auto& byArg : live_after)
|
||||
{
|
||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> converted;
|
||||
converted[byArg.first] = vector<SAPFOR::BasicBlock*>(byArg.second.begin(), byArg.second.end());
|
||||
|
||||
if (exit->addIn(converted))
|
||||
{
|
||||
exit->setInCnt(max_cnt);
|
||||
if (exit->forwardData(converted) != DATA_FLOW_UPD_STATUS::NO_CHANGE)
|
||||
exit->setOutCnt(max_cnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now we can update live sets in all blocks
|
||||
func_it->second->analyze();
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& byFunc : func_to_analysis_object)
|
||||
delete byFunc.second;
|
||||
|
||||
for (auto& byFunc : CFGraph_for_project)
|
||||
for (auto& byBlock : byFunc.second)
|
||||
byBlock->compressLives();
|
||||
|
||||
live_by_func.clear();
|
||||
dead_by_func.clear();
|
||||
}
|
||||
55
Sapfor/_src/CFGraph/live_variable_analysis.h
Normal file
55
Sapfor/_src/CFGraph/live_variable_analysis.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "CFGraph.h"
|
||||
|
||||
namespace LIVE_VARIABLES
|
||||
{
|
||||
/* Store information about live and dead variables after call operator */
|
||||
/* (needed for interprocedural part of live variable analysis) */
|
||||
class LiveDeadVarsForCall
|
||||
{
|
||||
private:
|
||||
bool tryInsert(std::set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b);
|
||||
public:
|
||||
FuncInfo* func;
|
||||
|
||||
std::map<int, std::set<SAPFOR::BasicBlock*>> live_after;
|
||||
std::set<int> dead_after;
|
||||
|
||||
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> commons_live_after;
|
||||
std::set<SAPFOR::Argument*> commons_dead_after;
|
||||
|
||||
std::vector<SAPFOR::Argument*> params;
|
||||
SAPFOR::BasicBlock* block;
|
||||
|
||||
LiveDeadVarsForCall(FuncInfo* f, SAPFOR::BasicBlock* b, const std::vector<SAPFOR::Argument*>& p);
|
||||
|
||||
void make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b);
|
||||
void make_dead(SAPFOR::Argument* arg);
|
||||
|
||||
void updateFromOut();
|
||||
};
|
||||
}
|
||||
|
||||
template <class IT, class DEST>
|
||||
void insertIfVar(IT begin, IT end, DEST& to) {
|
||||
for (auto it = begin; it != end; it++)
|
||||
if (*it && (*it)->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
to.insert(*it);
|
||||
}
|
||||
|
||||
void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
||||
std::set<SAPFOR::Argument*>& use, std::set<SAPFOR::Argument*>& def,
|
||||
std::vector<SAPFOR::Argument*>& formal_parameters, std::vector<LIVE_VARIABLES::LiveDeadVarsForCall>& fcalls,
|
||||
std::vector<SAPFOR::Argument*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
|
||||
bool& last_stack_op,
|
||||
std::string& fName, const std::map<std::string, FuncInfo*>& funcByName, bool interprocedural);
|
||||
|
||||
void runLiveVariableAnalysis(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project);
|
||||
|
||||
void doDumpLive(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project);
|
||||
|
||||
bool joinGlobalsWithParameters(const std::vector<SAPFOR::Argument*>& params,
|
||||
const std::map<std::string, std::pair<std::set<int>, std::set<SAPFOR::Argument*>>>& params_and_globals,
|
||||
const std::string& func_name, std::set<SAPFOR::Argument*>& result);
|
||||
539
Sapfor/_src/CFGraph/private_variables_analysis.cpp
Normal file
539
Sapfor/_src/CFGraph/private_variables_analysis.cpp
Normal file
@@ -0,0 +1,539 @@
|
||||
#include "../Utils/errors.h"
|
||||
#include "private_variables_analysis.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "../LoopAnalyzer/loop_analyzer.h"
|
||||
#include "../SageAnalysisTool/depGraph.h"
|
||||
#include "../DirectiveProcessing/directive_parser.h"
|
||||
#include "live_variable_analysis.h"
|
||||
#include "RD_subst.h"
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <list>
|
||||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::pair;
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using std::set;
|
||||
using std::unordered_set;
|
||||
using std::unordered_map;
|
||||
using std::list;
|
||||
|
||||
static map<string, pair<set<int>, set<SAPFOR::Argument*>>> outForFunc;
|
||||
static unordered_map<SgSymbol*, string> global_cache, local_cache;
|
||||
|
||||
static unordered_map <SAPFOR::Argument*, SgSymbol*> argumentToSymbol;
|
||||
|
||||
#define DEBUG_PRINT_PRIVATE 0
|
||||
|
||||
#define PRINT_PRIVATES 1
|
||||
#define PRINT_WARNINGS 1
|
||||
// print privates and lastprivates for loop
|
||||
void printLoopInfo(const LoopGraph* loop)
|
||||
{
|
||||
SgForStmt* loop_stmt = isSgForStmt(loop->loop);
|
||||
|
||||
const set<string>& priv = loop->privateScalars;
|
||||
const set<string>& lastpriv = loop->lastprivateScalars;
|
||||
|
||||
if(!loop_stmt)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
__spf_print(PRINT_PRIVATES, " loop in file '%s' at line %d\n", loop->fileName.c_str(), loop->lineNum);
|
||||
__spf_print(PRINT_PRIVATES, " privates:");
|
||||
for(const auto& ident : priv)
|
||||
__spf_print(PRINT_PRIVATES, " %s", ident.c_str());
|
||||
__spf_print(PRINT_PRIVATES, "\n lastprivates:");
|
||||
for (const auto& ident : lastpriv)
|
||||
__spf_print(PRINT_PRIVATES, " %s", ident.c_str());
|
||||
__spf_print(PRINT_PRIVATES, "\n");
|
||||
|
||||
if (PRINT_WARNINGS)
|
||||
{
|
||||
set<string> added;
|
||||
for (auto& data : getAttributes<SgStatement*, SgStatement*>(loop_stmt, set<int>{ SPF_ANALYSIS_DIR }))
|
||||
fillPrivatesFromComment(new Statement(data), added);
|
||||
|
||||
|
||||
set<string> extra_old;
|
||||
std::set_difference(added.begin(), added.end(), priv.begin(), priv.end(), std::inserter(extra_old, extra_old.begin()));
|
||||
|
||||
if (extra_old.size() != 0)
|
||||
{
|
||||
__spf_print(PRINT_WARNINGS, " [WARNING] extra private variables:");
|
||||
for (const auto& ident : extra_old)
|
||||
__spf_print(PRINT_WARNINGS, " %s", ident.c_str());
|
||||
__spf_print(PRINT_WARNINGS, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if parent statement contains stmt
|
||||
static bool isParentStmt(SgStatement* stmt, SgStatement* parent)
|
||||
{
|
||||
for (; stmt; stmt = stmt->controlParent())
|
||||
if (stmt == parent)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// iterate over expr tree and find SgSymbol that matches arg (by name)
|
||||
static SgSymbol* findSymbolByArgInExpression(const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
||||
const FuncInfo* func, const SAPFOR::Argument* arg, SgExpression* expr)
|
||||
{
|
||||
if (!expr)
|
||||
return NULL;
|
||||
|
||||
if (expr->symbol() && expr->symbol()->identifier() && getArgNameBySymbol(commonVars, func, expr->symbol(), global_cache, local_cache) == arg->getValue())
|
||||
return expr->symbol();
|
||||
|
||||
SgSymbol* left;
|
||||
if (left = findSymbolByArgInExpression(commonVars, func, arg, expr->lhs()))
|
||||
return left;
|
||||
|
||||
return findSymbolByArgInExpression(commonVars, func, arg, expr->rhs());
|
||||
}
|
||||
|
||||
// find SgSymbol that matches arg (by name) in stmt
|
||||
static SgSymbol* findSymbolByArgInStatement(const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
||||
const FuncInfo* func, const SAPFOR::Argument* arg, SgStatement* stmt)
|
||||
{
|
||||
if (!stmt)
|
||||
return NULL;
|
||||
|
||||
if (stmt->hasSymbol() && stmt->symbol() &&
|
||||
getArgNameBySymbol(commonVars, func, stmt->symbol(), global_cache, local_cache) == arg->getValue())
|
||||
{
|
||||
return stmt->symbol();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
SgSymbol* found = findSymbolByArgInExpression(commonVars, func, arg, stmt->expr(i));
|
||||
if (found)
|
||||
return found;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// find SgSymbol for arg in instr's operator and fill argumentToSymbol
|
||||
// do nothing if arg already has found symbol
|
||||
static void addPlaceWithDef(const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
||||
const FuncInfo* func, SAPFOR::Argument* arg, SAPFOR::Instruction* instr) {
|
||||
if (argumentToSymbol.find(arg) != argumentToSymbol.end())
|
||||
return;
|
||||
|
||||
SgStatement* stmt_with_decl = instr->getOperator();
|
||||
if (!stmt_with_decl)
|
||||
return;
|
||||
|
||||
SgSymbol* found = findSymbolByArgInStatement(commonVars, func, arg, stmt_with_decl);
|
||||
|
||||
if (found)
|
||||
argumentToSymbol[arg] = found;
|
||||
|
||||
}
|
||||
|
||||
static void getDefined(const string& func, const vector<SAPFOR::Argument*>& params,
|
||||
set<SAPFOR::Argument*>& result)
|
||||
{
|
||||
if (!joinGlobalsWithParameters(params, outForFunc, func, result))
|
||||
{
|
||||
if (func == string("_WRITE") || isIntrinsic(func.c_str()))
|
||||
return;
|
||||
else //READ or else
|
||||
insertIfVar(params.begin(), params.end(), result);
|
||||
}
|
||||
}
|
||||
|
||||
static void fillOutForFunc(const FuncInfo* func, const vector<SAPFOR::BasicBlock*>& blocks)
|
||||
{
|
||||
if (blocks.size() == 0)
|
||||
return;
|
||||
|
||||
set<SAPFOR::BasicBlock*> exits = {};
|
||||
|
||||
for (auto block : blocks)
|
||||
{
|
||||
if (block->getNext().size() == 0)
|
||||
exits.insert(block);
|
||||
}
|
||||
|
||||
set<int> defined;
|
||||
set<SAPFOR::Argument*> common_defined;
|
||||
|
||||
for (auto byExit : exits)
|
||||
{
|
||||
for (const auto& byRd : byExit->getRD_Out())
|
||||
{
|
||||
auto out_arg = byRd.first;
|
||||
if (!(byRd.second.size() == 1 && *(byRd.second.begin()) < 0))
|
||||
{
|
||||
switch (out_arg->getMemType())
|
||||
{
|
||||
case SAPFOR::CFG_MEM_TYPE::COMMON_:
|
||||
case SAPFOR::CFG_MEM_TYPE::MODULE_:
|
||||
common_defined.insert(out_arg);
|
||||
break;
|
||||
case SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_:
|
||||
{
|
||||
int num = getParamIndex(out_arg, func->funcParams.countOfPars);
|
||||
if(func->funcParams.isArgOut(num))
|
||||
defined.insert(num);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
outForFunc[func->funcName] = { defined, common_defined };
|
||||
}
|
||||
|
||||
static void getDefsFromBlock(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& res,
|
||||
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
||||
const FuncInfo* func)
|
||||
{
|
||||
vector<SAPFOR::Argument*> lastParamRef;
|
||||
|
||||
for (auto ir_block : block->getInstructions())
|
||||
{
|
||||
SAPFOR::Instruction* instr = ir_block->getInstruction();
|
||||
SAPFOR::CFG_OP instr_operation = instr->getOperation();
|
||||
if (instr_operation == SAPFOR::CFG_OP::PARAM)
|
||||
{
|
||||
SAPFOR::Argument* arg = instr->getArg1();
|
||||
if(arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
addPlaceWithDef(commonVars, func, arg, instr);
|
||||
|
||||
lastParamRef.push_back(arg);
|
||||
}
|
||||
else if (instr_operation == SAPFOR::CFG_OP::F_CALL)
|
||||
{
|
||||
int count = stoi(instr->getArg2()->getValue());
|
||||
if (lastParamRef.size() != count)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
const string& fName = instr->getArg1()->getValue();
|
||||
|
||||
getDefined(fName, lastParamRef, res);
|
||||
|
||||
lastParamRef.clear();
|
||||
}
|
||||
}
|
||||
|
||||
int first_instr_num = block->getInstructions().front()->getNumber();
|
||||
int last_instr_num = block->getInstructions().back()->getNumber();
|
||||
|
||||
for (const auto& def : block->getRD_Out())
|
||||
for (int place : def.second)
|
||||
if (place >= first_instr_num && place <= last_instr_num && def.first->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
{
|
||||
res.insert(def.first);
|
||||
addPlaceWithDef(commonVars, func, def.first, block->getInstructions()[place - first_instr_num]->getInstruction());
|
||||
}
|
||||
}
|
||||
|
||||
// recursively analyze FOR loops
|
||||
static set<SAPFOR::BasicBlock*> analyzeLoop(LoopGraph* loop, const set<SAPFOR::BasicBlock*>& blocks,
|
||||
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
||||
const map<string, SgSymbol*>& commonArgs, FuncInfo* func,
|
||||
map<string, vector<Messages>>& messages)
|
||||
{
|
||||
if (!loop->isFor)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__); //should be called only with FOR loops
|
||||
|
||||
SgStatement* loop_operator = loop->loop->GetOriginal();
|
||||
|
||||
// find blocks related to the current loop
|
||||
set<SAPFOR::BasicBlock*> currentLoop = { };
|
||||
|
||||
/*
|
||||
service block that looks like
|
||||
_reg = _reg < _reg
|
||||
IF_FALSE _reg then goto ...
|
||||
*/
|
||||
SAPFOR::BasicBlock* head_block = NULL;
|
||||
|
||||
int loop_start = loop->lineNum, loop_end = loop->lineNumAfterLoop;
|
||||
for (auto bb : blocks)
|
||||
{
|
||||
if (!bb || (bb->getInstructions().size() == 0))
|
||||
continue;
|
||||
|
||||
SgStatement* first = bb->getInstructions().front()->getInstruction()->getOperator();
|
||||
SgStatement* last = bb->getInstructions().back()->getInstruction()->getOperator();
|
||||
|
||||
if (isParentStmt(first, loop_operator) && isParentStmt(last, loop_operator))
|
||||
{
|
||||
currentLoop.insert(bb);
|
||||
|
||||
if ((!head_block) && (first == loop_operator) && (last == loop_operator) &&
|
||||
(bb->getInstructions().size() == 2) &&
|
||||
(bb->getInstructions().back()->getInstruction()->getOperation() == SAPFOR::CFG_OP::JUMP_IF))
|
||||
{
|
||||
head_block = bb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!head_block)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
// find blocks inside loop wich can lead to head_block
|
||||
list<SAPFOR::BasicBlock*> search_stack = { head_block };
|
||||
set<SAPFOR::BasicBlock*> cycleBody = { };
|
||||
|
||||
while (search_stack.size() > 0)
|
||||
{
|
||||
SAPFOR::BasicBlock* curr = search_stack.front();
|
||||
search_stack.pop_front();
|
||||
|
||||
if (cycleBody.insert(curr).second)
|
||||
for (auto next : curr->getPrev())
|
||||
if (currentLoop.count(next))
|
||||
search_stack.push_back(next);
|
||||
}
|
||||
|
||||
set<SAPFOR::Argument*> useValueInLoop = {};
|
||||
|
||||
for (const auto& use : head_block->getLiveIn())
|
||||
{
|
||||
for (SAPFOR::BasicBlock* place : use.second)
|
||||
{
|
||||
if (currentLoop.count(place))
|
||||
{
|
||||
useValueInLoop.insert(use.first);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set<SAPFOR::Argument*> changeValueInLoop = { };
|
||||
set<SAPFOR::Argument*> changeValueOnExit = { };
|
||||
set<SAPFOR::Argument*> LiveWhenLoopEnds = { };
|
||||
|
||||
auto loop_it = currentLoop.begin();
|
||||
auto loop_end_it = currentLoop.end();
|
||||
|
||||
auto body_it = cycleBody.begin();
|
||||
auto body_end = cycleBody.end();
|
||||
|
||||
while ((loop_it != loop_end_it) && (body_it != body_end))
|
||||
{
|
||||
if (*loop_it == *body_it)
|
||||
{
|
||||
getDefsFromBlock(*loop_it, changeValueInLoop, commonVars, func);
|
||||
body_it++;
|
||||
}
|
||||
else
|
||||
getDefsFromBlock(*loop_it, changeValueOnExit, commonVars, func);
|
||||
loop_it++;
|
||||
}
|
||||
|
||||
if (body_it != body_end)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (; loop_it != loop_end_it; loop_it++)
|
||||
getDefsFromBlock(*loop_it, changeValueOnExit, commonVars, func);
|
||||
|
||||
|
||||
for (auto bb : currentLoop)
|
||||
{
|
||||
//fill LiveWhenLoopEnds
|
||||
bool has_next_outside_body = false;
|
||||
for (const auto& next : bb->getNext())
|
||||
{
|
||||
if (cycleBody.find(next) == cycleBody.end())
|
||||
{
|
||||
has_next_outside_body = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_next_outside_body)
|
||||
{
|
||||
for (const auto& use : bb->getLiveOut())
|
||||
for (SAPFOR::BasicBlock* place : use.second)
|
||||
if (currentLoop.count(place) == 0)
|
||||
{
|
||||
LiveWhenLoopEnds.insert(use.first);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set<SAPFOR::Argument*> arg_private = {}, arg_lastprivate = {};
|
||||
|
||||
std::set_difference(changeValueInLoop.begin(), changeValueInLoop.end(),
|
||||
useValueInLoop.begin(), useValueInLoop.end(),
|
||||
std::inserter(arg_private, arg_private.begin()));
|
||||
|
||||
arg_private.insert(changeValueOnExit.begin(), changeValueOnExit.end());
|
||||
|
||||
std::set_intersection(arg_private.begin(), arg_private.end(),
|
||||
LiveWhenLoopEnds.begin(), LiveWhenLoopEnds.end(),
|
||||
std::inserter(arg_lastprivate, arg_lastprivate.begin()));
|
||||
|
||||
changeValueInLoop.clear();
|
||||
LiveWhenLoopEnds.clear();
|
||||
useValueInLoop.clear();
|
||||
|
||||
vector<const depNode*> sym_private;
|
||||
for (auto e : arg_private)
|
||||
{
|
||||
SgSymbol* arg_sym = NULL;
|
||||
|
||||
auto it = argumentToSymbol.find(e);
|
||||
if (it != argumentToSymbol.end())
|
||||
arg_sym = it->second;
|
||||
else if (e->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || e->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
|
||||
continue;
|
||||
|
||||
if (arg_sym && arg_sym->identifier())
|
||||
{
|
||||
if (arg_lastprivate.find(e) != arg_lastprivate.end())
|
||||
{
|
||||
loop->lastprivateScalars.insert(arg_sym->identifier());
|
||||
|
||||
const char* identifier = arg_sym->identifier();
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"add lastprivate scalar '%s' to loop on line %d", to_wstring(identifier).c_str(), loop->lineNum);
|
||||
__spf_printToLongBuf(messageR, R200, to_wstring(identifier).c_str(), loop->lineNum);
|
||||
|
||||
messages[loop->fileName].push_back(Messages(NOTE, loop->lineNum, messageR, messageE, 3002));
|
||||
}
|
||||
else
|
||||
{
|
||||
SgStatement* s = new SgStatement(0);
|
||||
s->setlineNumber(loop_start);
|
||||
|
||||
SgExpression* exp = new SgExpression(VAR_REF);
|
||||
exp->setSymbol(arg_sym);
|
||||
|
||||
sym_private.push_back(new depNode(s, s, exp, exp, 0, 0, NULL, NULL, 0));
|
||||
loop->privateScalars.insert(arg_sym->identifier());
|
||||
}
|
||||
}
|
||||
else
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
addPrivatesToLoops(loop, sym_private, { {loop_start, isSgForStmt(loop_operator)} }, messages[loop->fileName]);
|
||||
|
||||
for (const depNode* node : sym_private)
|
||||
{
|
||||
delete node->stmtin;
|
||||
delete node;
|
||||
}
|
||||
|
||||
arg_private.clear();
|
||||
arg_lastprivate.clear();
|
||||
|
||||
printLoopInfo(loop);
|
||||
return currentLoop;
|
||||
}
|
||||
|
||||
|
||||
static void recAnalyzeLoop(LoopGraph* loop, const set<SAPFOR::BasicBlock*>& blocks,
|
||||
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
||||
const map<string, SgSymbol*>& commonArgs,
|
||||
FuncInfo* func, map<string, vector<Messages>>& messages)
|
||||
{
|
||||
const auto& loop_body = loop->isFor ? analyzeLoop(loop, blocks, commonVars, commonArgs, func, messages) : blocks;
|
||||
|
||||
for (const auto& inner_loop : loop->children)
|
||||
recAnalyzeLoop(inner_loop, loop_body, commonVars, commonArgs, func, messages);
|
||||
}
|
||||
|
||||
void runPrivateVariableAnalysis(const map<string, vector<LoopGraph*>>& loopGraph,
|
||||
const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project,
|
||||
const map<string, CommonBlock*>& commonBlocks,
|
||||
map<string, vector<Messages>>& messages)
|
||||
{
|
||||
map<string, FuncInfo*> funcByName;
|
||||
for (const auto& byFunc : CFGraph_for_project)
|
||||
if (byFunc.first)
|
||||
funcByName[byFunc.first->funcName] = byFunc.first;
|
||||
|
||||
|
||||
//fill outForFunc
|
||||
for (const auto& byLoopFunc : loopGraph)
|
||||
{
|
||||
for (const auto& byLoop : byLoopFunc.second)
|
||||
{
|
||||
for (const auto& byFuncCall : byLoop->calls)
|
||||
{
|
||||
const string& fname = byFuncCall.first;
|
||||
if (outForFunc.find(fname) == outForFunc.end())
|
||||
{
|
||||
auto func_it = funcByName.find(fname);
|
||||
if (func_it != funcByName.end())
|
||||
{
|
||||
FuncInfo* func = func_it->second;
|
||||
auto cfg_it = CFGraph_for_project.find(func);
|
||||
if (cfg_it == CFGraph_for_project.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
fillOutForFunc(cfg_it->first, cfg_it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map<FuncInfo*, map<string, SgSymbol*>> commonArgsByFunc = { };
|
||||
for (const auto& byFile : loopGraph)
|
||||
{
|
||||
SgFile::switchToFile(byFile.first);
|
||||
|
||||
for (auto loop : byFile.second)
|
||||
{
|
||||
int loop_start = loop->lineNum, loop_end = loop->lineNumAfterLoop;
|
||||
|
||||
SgStatement* search_func = loop->loop->GetOriginal();
|
||||
|
||||
while (search_func && (!isSgProgHedrStmt(search_func)))
|
||||
search_func = search_func->controlParent();
|
||||
|
||||
if(!search_func)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__); //loop statement outside any function statement
|
||||
|
||||
bool loop_analyzed = false;
|
||||
for (const auto& byFunc : CFGraph_for_project)
|
||||
{
|
||||
if (byFunc.first->fileName == byFile.first && byFunc.first->funcPointer->GetOriginal() == search_func)
|
||||
{
|
||||
const auto& commonVars = getCommonsByFunction(current_file, byFunc.first->funcPointer, commonBlocks);
|
||||
const auto& commonArgs = getCommonArgsByFunc(byFunc.first, commonArgsByFunc, commonVars, global_cache, local_cache);
|
||||
|
||||
set<SAPFOR::BasicBlock*> loop_ir;
|
||||
loop_ir.insert(byFunc.second.begin(), byFunc.second.end());
|
||||
recAnalyzeLoop(loop, loop_ir, commonVars, commonArgs, byFunc.first, messages);
|
||||
argumentToSymbol.clear(); //clear cache
|
||||
loop_analyzed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!loop_analyzed)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__); //no func found for loop
|
||||
}
|
||||
|
||||
local_cache.clear();
|
||||
commonArgsByFunc.clear();
|
||||
}
|
||||
|
||||
outForFunc.clear();
|
||||
global_cache.clear();
|
||||
}
|
||||
11
Sapfor/_src/CFGraph/private_variables_analysis.h
Normal file
11
Sapfor/_src/CFGraph/private_variables_analysis.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "CFGraph.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
void runPrivateVariableAnalysis(const std::map<std::string, std::vector<LoopGraph*>>& loopGraph,
|
||||
const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project,
|
||||
const std::map<std::string, CommonBlock*>& commonBlocks,
|
||||
std::map<std::string, std::vector<Messages>>& messages);
|
||||
882
Sapfor/_src/CreateInterTree/CreateInterTree.cpp
Normal file
882
Sapfor/_src/CreateInterTree/CreateInterTree.cpp
Normal file
@@ -0,0 +1,882 @@
|
||||
#include "CreateInterTree.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../GraphCall/graph_calls_func.h"
|
||||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::vector;
|
||||
using std::list;
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::set;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::fstream;
|
||||
|
||||
static long int getNextTag()
|
||||
{
|
||||
static long int INTERVAL_TAG = 0;
|
||||
return INTERVAL_TAG++;
|
||||
}
|
||||
|
||||
//Debug funcs
|
||||
static void printTree(SpfInterval* inter, fstream &file, int level)
|
||||
{
|
||||
if (!(inter->ifInclude))
|
||||
{
|
||||
for (int i = 0; i < inter->nested.size(); i++)
|
||||
printTree(inter->nested[i], file, level + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!inter->begin->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (int i = 0; i < level; i++)
|
||||
file << " ";
|
||||
file << " Begin INTERVAL #" << inter->tag << " (var " << tag[inter->begin->variant()];
|
||||
if (inter->begin->variant() == PROC_HEDR || inter->begin->variant() == FUNC_HEDR)
|
||||
{
|
||||
string name(inter->begin->symbol()->identifier());
|
||||
convertToUpper(name);
|
||||
file << ", " << name;
|
||||
}
|
||||
file << ", gcov_calls " << inter->calls_count << ") ";
|
||||
file << " [" << inter->lineFile.first << ", " << inter->lineFile.second << "]";
|
||||
if (inter->parent == NULL && level != 0)
|
||||
file << " -- through PROC_CALL --";
|
||||
file << "\n";
|
||||
|
||||
for (int i = 0; i < inter->nested.size(); i++)
|
||||
printTree(inter->nested[i], file, level + 1);
|
||||
|
||||
for (int i = 0; i < inter->ends.size(); i++)
|
||||
{
|
||||
for (int i = 0; i < level; i++)
|
||||
file << " ";
|
||||
file << " End INTERVAL #" << inter->tag << " (exit lvl " << inter->exit_levels[i] << ", var " << tag[inter->ends[i]->variant()] << ") ";
|
||||
file << "line " << inter->ends[i]->lineNumber() << endl;
|
||||
}
|
||||
if (level == 0)
|
||||
file << endl;
|
||||
}
|
||||
|
||||
void saveIntervals(const string &fileName, map<string, vector<SpfInterval*>> &intervals)
|
||||
{
|
||||
fstream file_intervals;
|
||||
|
||||
file_intervals.open(fileName, fstream::out);
|
||||
for (auto &byfile : intervals)
|
||||
{
|
||||
file_intervals << "**** INTERVALS FOR FILE '" << byfile.first << "'\n";
|
||||
for (auto &interval : byfile.second)
|
||||
printTree(interval, file_intervals, 0);
|
||||
}
|
||||
file_intervals.close();
|
||||
}
|
||||
|
||||
//Labels funcs
|
||||
static void matchGotoLabels(SgStatement *st, map<int, vector<int>> &gotoStmts)
|
||||
{
|
||||
map<int, vector<int>> labelsRef;
|
||||
|
||||
findAllRefsToLables(st, labelsRef, false);
|
||||
|
||||
for (auto &key : labelsRef)
|
||||
for (auto &it : key.second)
|
||||
gotoStmts[it].push_back(key.first);
|
||||
}
|
||||
|
||||
static void findAllLabels(SgStatement* st, map<int, int> &labelsRef)
|
||||
{
|
||||
SgStatement* end = st->lastNodeOfStmt();
|
||||
|
||||
while (st != end)
|
||||
{
|
||||
if (st->hasLabel())
|
||||
labelsRef[st->label()->id()] = st->lineNumber();
|
||||
st = st->lexNext();
|
||||
}
|
||||
if (end->hasLabel())
|
||||
labelsRef[end->label()->id()] = end->lineNumber();
|
||||
}
|
||||
|
||||
//Nested intervals removal
|
||||
static int getNestedLevel(SgStatement* loop_stmt)
|
||||
{
|
||||
int depth = 0;
|
||||
SgStatement *current_loop = loop_stmt->lexNext();
|
||||
SgStatement* controlEnd = loop_stmt->lastNodeOfStmt()->lexPrev();
|
||||
SgStatement *controlEnd2 = current_loop->lastNodeOfStmt();
|
||||
|
||||
while (isSgForStmt(current_loop) && isSgControlEndStmt(controlEnd) && controlEnd == controlEnd2)
|
||||
{
|
||||
current_loop = current_loop->lexNext();
|
||||
controlEnd = controlEnd->lexPrev();
|
||||
controlEnd2 = current_loop->lastNodeOfStmt();
|
||||
depth++;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
static void removeNestedIntervals(SpfInterval* interval)
|
||||
{
|
||||
if (isSgForStmt(interval->begin))
|
||||
{
|
||||
int depth = getNestedLevel(interval->begin);
|
||||
SpfInterval *current_interval = interval;
|
||||
|
||||
for (int i = 0; i < depth; i++)
|
||||
{
|
||||
current_interval = current_interval->nested[0];
|
||||
current_interval->ifInclude = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &include : interval->nested)
|
||||
removeNestedIntervals(include);
|
||||
}
|
||||
|
||||
// Merge trees functions.
|
||||
static int compareIntervals(SpfInterval* interval1, SpfInterval* interval2)
|
||||
{
|
||||
SgStatement* begin_st_1 = interval1->begin;
|
||||
while (!isSgExecutableStatement(begin_st_1) || isSPF_stat(begin_st_1) || isDVM_stat(begin_st_1))
|
||||
begin_st_1 = begin_st_1->lexNext();
|
||||
|
||||
SgStatement* begin_st_2 = interval2->begin;
|
||||
while (!isSgExecutableStatement(begin_st_2) || isSPF_stat(begin_st_2) || isDVM_stat(begin_st_2))
|
||||
begin_st_2 = begin_st_2->lexNext();
|
||||
|
||||
int begin_1 = begin_st_1->lineNumber();
|
||||
int begin_2 = begin_st_2->lineNumber();
|
||||
int end_1 = interval1->ends[0]->lineNumber();
|
||||
int end_2 = interval2->ends[0]->lineNumber();
|
||||
|
||||
if((begin_1 == begin_2 && end_1 == end_2) || end_1 <= begin_2 || begin_1 >= end_2)
|
||||
return 0;
|
||||
|
||||
if(begin_1 <= begin_2 && end_1 >= end_2)
|
||||
return 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void insertIntervalIntoTree(vector<SpfInterval*> &tree, SpfInterval* userInterval)
|
||||
{
|
||||
bool ifDeleteNested = false;
|
||||
|
||||
for(int i = 0; i < tree.size(); i++)
|
||||
{
|
||||
int compare_result = compareIntervals(tree[i], userInterval);
|
||||
|
||||
if(compare_result == 0)
|
||||
continue;
|
||||
|
||||
if(compare_result > 0)
|
||||
{
|
||||
int amount = 0;
|
||||
|
||||
for(int j = 1; j < tree[i]->ends.size(); j++)
|
||||
{
|
||||
int endLineNumber = tree[i]->ends[j]->lineNumber();
|
||||
|
||||
if(endLineNumber >= userInterval->begin->lineNumber() && endLineNumber <= userInterval->ends[0]->lineNumber())
|
||||
{
|
||||
userInterval->ends.push_back(tree[i]->ends[j]);
|
||||
userInterval->exit_levels.push_back(0);
|
||||
|
||||
tree[i]->ends[j] = NULL;
|
||||
amount++;
|
||||
}
|
||||
}
|
||||
|
||||
tree[i]->ends.erase(std::remove_if(tree[i]->ends.begin(), tree[i]->ends.end(), [](SgStatement* stmt) {return (stmt == NULL);}), tree[i]->ends.end());
|
||||
for(int j = 0; j < amount; j++)
|
||||
tree[i]->exit_levels.pop_back();
|
||||
|
||||
insertIntervalIntoTree(tree[i]->nested, userInterval);
|
||||
return;
|
||||
}
|
||||
|
||||
userInterval->nested.push_back(tree[i]);
|
||||
userInterval->parent = tree[i]->parent;
|
||||
tree[i]->parent = userInterval;
|
||||
tree[i] = userInterval;
|
||||
|
||||
if(ifDeleteNested)
|
||||
tree[i] = NULL;
|
||||
else
|
||||
ifDeleteNested = true;
|
||||
}
|
||||
|
||||
tree.erase(std::remove_if(tree.begin(), tree.end(), [](SpfInterval* interval) {return (interval == NULL);}), tree.end());
|
||||
}
|
||||
|
||||
static void mergeTrees(vector<SpfInterval*> &fileIntervals, vector<SpfInterval*> &userIntervals)
|
||||
{
|
||||
for(auto &userInterval : userIntervals)
|
||||
insertIntervalIntoTree(fileIntervals, userInterval);
|
||||
}
|
||||
|
||||
// Calibrate interval exits.
|
||||
static void calibrateExits(const vector<SpfInterval*>& fileIntervals, const map<int, int> &labelsRef, map<int, vector<int>> &gotoStmts, int level)
|
||||
{
|
||||
for(auto &interval : fileIntervals)
|
||||
{
|
||||
for(int i = 1; i < interval->ends.size(); i++)
|
||||
{
|
||||
int variant = interval->ends[i]->variant();
|
||||
int &exit_level = interval->exit_levels[i];
|
||||
|
||||
if (variant == RETURN_STAT || variant == STOP_STAT || variant == EXIT_STMT)
|
||||
exit_level = level;
|
||||
|
||||
if (variant == EXIT_STMT)
|
||||
exit_level = 1;
|
||||
|
||||
for (auto&lab : gotoStmts[interval->ends[i]->lineNumber()])
|
||||
{
|
||||
auto itL = labelsRef.find(lab);
|
||||
if (itL == labelsRef.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
const int label_line = itL->second;
|
||||
if (label_line == 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
int depth = 0;
|
||||
|
||||
SpfInterval* searchInterval = interval;
|
||||
while (label_line < searchInterval->begin->lineNumber() || label_line > searchInterval->ends[0]->lineNumber())
|
||||
{
|
||||
searchInterval = searchInterval->parent;
|
||||
depth++;
|
||||
if (searchInterval == NULL)
|
||||
break;
|
||||
}
|
||||
exit_level = depth;
|
||||
}
|
||||
}
|
||||
|
||||
calibrateExits(interval->nested, labelsRef, gotoStmts, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void removeUserIntervals(SgFile *file)
|
||||
{
|
||||
for (SgStatement* st = file->firstStatement(); st; st = st->lexNext())
|
||||
{
|
||||
const int var = st->variant();
|
||||
if (var == DVM_INTERVAL_DIR || var == DVM_EXIT_INTERVAL_DIR || var == DVM_ENDINTERVAL_DIR)
|
||||
{
|
||||
//move comment to next statement
|
||||
if (st->comments())
|
||||
{
|
||||
const char* comms = st->comments();
|
||||
string comments(comms);
|
||||
st->delComments();
|
||||
|
||||
SgStatement* next = st->lexNext();
|
||||
if (next)
|
||||
next->addComment(comments.c_str());
|
||||
}
|
||||
|
||||
st = st->lexPrev();
|
||||
st->lexNext()->deleteStmt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find intervals functions.
|
||||
static void findUserIntervals(SgStatement *startSt, vector<SpfInterval*> &userIntervals, vector<Messages> &messages)
|
||||
{
|
||||
SpfInterval *currentInterval = NULL;
|
||||
|
||||
SgStatement *endSt = startSt->lastNodeOfStmt();
|
||||
SgStatement *currentSt = startSt;
|
||||
|
||||
set<SpfInterval*> userIntervalsSet;
|
||||
|
||||
while (currentSt != endSt)
|
||||
{
|
||||
if(currentSt->variant() == DVM_INTERVAL_DIR)
|
||||
{
|
||||
SgStatement* begin = currentSt;
|
||||
while (isDVM_stat(begin))
|
||||
begin = begin->lexNext();
|
||||
|
||||
SpfInterval *inter = new SpfInterval(currentSt->lineNumber());
|
||||
inter->begin = begin;
|
||||
inter->lineFile = std::make_pair(begin->lineNumber(), begin->fileName());
|
||||
inter->parent = currentInterval;
|
||||
inter->tag = getNextTag();
|
||||
|
||||
userIntervals.push_back(inter);
|
||||
|
||||
currentInterval = inter;
|
||||
userIntervalsSet.insert(currentInterval);
|
||||
}
|
||||
|
||||
if(currentSt->variant() == DVM_ENDINTERVAL_DIR)
|
||||
{
|
||||
if (currentInterval == NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
SgStatement* end = currentSt;
|
||||
while(isDVM_stat(end))
|
||||
end = end->lexPrev();
|
||||
|
||||
currentInterval->ends.push_back(end);
|
||||
currentInterval->exit_levels.push_back(0);
|
||||
|
||||
currentInterval = currentInterval->parent;
|
||||
}
|
||||
|
||||
currentSt = currentSt->lexNext();
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
//check for ends
|
||||
for (auto& inter : userIntervalsSet)
|
||||
{
|
||||
if (inter->begin == NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (inter->ends.size() == 0)
|
||||
{
|
||||
wstring messageR, messageE;
|
||||
__spf_printToLongBuf(messageE, L"Can not find end of DVM's interval");
|
||||
__spf_printToLongBuf(messageR, R150);
|
||||
|
||||
messages.push_back(Messages(ERROR, inter->userIntervalLine, messageR, messageE, 1052));
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (error)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
static void findIntervals(SpfInterval *interval, map<int, int> &labelsRef, map<int, vector<int>> &gotoStmts, SgStatement *¤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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
75
Sapfor/_src/CreateInterTree/CreateInterTree.h
Normal file
75
Sapfor/_src/CreateInterTree/CreateInterTree.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "dvm.h"
|
||||
|
||||
#include "../GraphLoop/graph_loops_func.h"
|
||||
|
||||
struct SpfInterval
|
||||
{
|
||||
int userIntervalLine;
|
||||
|
||||
int tag = 0;
|
||||
long long calls_count = 0;
|
||||
bool ifInclude = true;
|
||||
|
||||
bool isRegion;
|
||||
bool isNested;
|
||||
|
||||
SgStatement *begin;
|
||||
std::pair<int, std::string> lineFile;
|
||||
SpfInterval *parent;
|
||||
|
||||
std::vector<SgStatement*> ends;
|
||||
std::vector<int> exit_levels;
|
||||
std::vector<SpfInterval*> nested;
|
||||
|
||||
//TODO: to be delete or rewrite with new predictor
|
||||
//from statistic after execution
|
||||
int exec_count = 0;
|
||||
double exec_time = 0;
|
||||
std::vector<double> predictedTimes;
|
||||
std::vector<double> predictedRemoteTimes;
|
||||
|
||||
|
||||
SpfInterval(int line)
|
||||
{
|
||||
userIntervalLine = line;
|
||||
begin = NULL;
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
int getBestTimeIdx()
|
||||
{
|
||||
int idx = -1;
|
||||
double best = 0;
|
||||
for (int z = 0; z < predictedTimes.size(); ++z)
|
||||
{
|
||||
if (idx == -1 || best > predictedTimes[z])
|
||||
{
|
||||
best = predictedTimes[z];
|
||||
idx = z;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
};
|
||||
|
||||
void saveIntervals(const std::string &fileName, std::map<std::string, std::vector<SpfInterval*>> &intervals);
|
||||
void createInterTree(SgFile*, std::vector<SpfInterval*>&, bool, std::vector<Messages>&);
|
||||
void assignCallsToFile(const std::string&, std::vector<SpfInterval*>&);
|
||||
void removeNodes(int, std::vector<SpfInterval*>&, std::vector<std::string>&);
|
||||
void insertIntervals(SgFile*, const std::vector<SpfInterval*>&);
|
||||
void createMapOfinterval(std::map<int, SpfInterval*> &mapIntervals, const std::vector<SpfInterval*> &intervals);
|
||||
void initTimeForIntervalTree(const int numOfTopologies, std::vector<SpfInterval*> &intervals);
|
||||
void aggregatePredictedTimes(std::vector<SpfInterval*> &itervals);
|
||||
SpfInterval* getMainInterval(SgProject *project, const std::map<std::string, std::vector<SpfInterval*>> &intervals, std::map<std::string, std::vector<Messages>>& SPF_messages);
|
||||
void uniteIntervalsBetweenProcCalls(std::map<std::string, std::vector<SpfInterval*>> &intervals, const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo);
|
||||
SpfInterval* findNearestUp(const std::map<SgStatement*, SpfInterval*> &intervals, SgStatement *st);
|
||||
SpfInterval* findNearestDown(const std::map<SgStatement*, SpfInterval*> &intervals, SgStatement *st);
|
||||
92
Sapfor/_src/DirectiveProcessing/directive_analyzer.cpp
Normal file
92
Sapfor/_src/DirectiveProcessing/directive_analyzer.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <assert.h>
|
||||
|
||||
#include "../Distribution/DvmhDirective.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "directive_analyzer.h"
|
||||
#include "../Utils/utils.h"
|
||||
|
||||
using std::vector;
|
||||
using std::map;
|
||||
|
||||
static void recUniteAcrossOut(LoopGraph *currLoop)
|
||||
{
|
||||
if (currLoop->perfectLoop > 1)
|
||||
{
|
||||
recUniteAcrossOut(currLoop->children[0]);
|
||||
if (currLoop->directive)
|
||||
currLoop->acrossOutAttribute.insert(currLoop->children[0]->acrossOutAttribute.begin(), currLoop->children[0]->acrossOutAttribute.end());
|
||||
}
|
||||
}
|
||||
|
||||
static void recUnite(vector<LoopGraph*> &loopGraph)
|
||||
{
|
||||
for (int i = 0; i < loopGraph.size(); ++i)
|
||||
{
|
||||
LoopGraph &currLoop = *loopGraph[i];
|
||||
if (currLoop.perfectLoop > 1)
|
||||
{
|
||||
vector<ParallelDirective*> united;
|
||||
vector<ParallelDirective*> elems;
|
||||
|
||||
LoopGraph *elem = loopGraph[i];
|
||||
for (int k = 0; k < currLoop.perfectLoop; ++k)
|
||||
{
|
||||
elems.push_back(elem->directive);
|
||||
if (k != currLoop.perfectLoop - 1)
|
||||
elem = elem->children[0];
|
||||
}
|
||||
|
||||
united.push_back(elems.back());
|
||||
for (int k = currLoop.perfectLoop - 2; k >= 0; --k)
|
||||
{
|
||||
ParallelDirective *first = elems[k];
|
||||
ParallelDirective *second = united.back();
|
||||
ParallelDirective *newDir = NULL;
|
||||
if (first != NULL && second != NULL)
|
||||
newDir = *first + *second;
|
||||
else if (first != NULL)
|
||||
newDir = new ParallelDirective(*first);
|
||||
else if (first == NULL && second != NULL)
|
||||
{
|
||||
newDir = new ParallelDirective(*second);
|
||||
newDir->parallel.insert(newDir->parallel.begin(), "*");
|
||||
}
|
||||
|
||||
united.push_back(newDir);
|
||||
}
|
||||
|
||||
elem = loopGraph[i];
|
||||
for (int k = 0; k < currLoop.perfectLoop - 1; ++k)
|
||||
{
|
||||
if (elem->directive)
|
||||
delete elem->directive;
|
||||
|
||||
elem->directive = united[currLoop.perfectLoop - k - 1];
|
||||
elem = elem->children[0];
|
||||
}
|
||||
recUniteAcrossOut(loopGraph[i]);
|
||||
}
|
||||
else
|
||||
recUnite(currLoop.children);
|
||||
}
|
||||
}
|
||||
|
||||
void UniteNestedDirectives(vector<LoopGraph*> &loopGraph)
|
||||
{
|
||||
recUnite(loopGraph);
|
||||
}
|
||||
6
Sapfor/_src/DirectiveProcessing/directive_analyzer.h
Normal file
6
Sapfor/_src/DirectiveProcessing/directive_analyzer.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
|
||||
void UniteNestedDirectives(std::vector<LoopGraph*> &loopGraph);
|
||||
490
Sapfor/_src/DirectiveProcessing/directive_creator.cpp
Normal file
490
Sapfor/_src/DirectiveProcessing/directive_creator.cpp
Normal file
@@ -0,0 +1,490 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <assert.h>
|
||||
|
||||
#include "dvm.h"
|
||||
|
||||
#include "../ParallelizationRegions/ParRegions_func.h"
|
||||
|
||||
#include "../Distribution/GraphCSR.h"
|
||||
#include "../Distribution/Arrays.h"
|
||||
#include "../Distribution/Distribution.h"
|
||||
#include "../Distribution/DvmhDirective_func.h"
|
||||
|
||||
#include "../Utils/errors.h"
|
||||
#include "../LoopAnalyzer/loop_analyzer.h"
|
||||
#include "directive_parser.h"
|
||||
#include "directive_creator.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../Sapfor.h"
|
||||
#include "../GraphLoop/graph_loops_func.h"
|
||||
#include "../Transformations/loop_transform.h"
|
||||
#include "../ExpressionTransform/expr_transform.h"
|
||||
#include "../GraphCall/graph_calls_func.h"
|
||||
|
||||
#include "../Utils/AstWrapper.h"
|
||||
|
||||
#define PRINT_DIR_RESULT 0
|
||||
|
||||
#define FIRST(x) get<0>(x)
|
||||
#define SECOND(x) get<1>(x)
|
||||
#define THIRD(x) get<2>(x)
|
||||
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
using std::tuple;
|
||||
using std::map;
|
||||
using std::set;
|
||||
using std::make_pair;
|
||||
using std::make_tuple;
|
||||
using std::get;
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
|
||||
extern int sharedMemoryParallelization;
|
||||
|
||||
static vector<pair<string, vector<Expression*>>>
|
||||
groupRealignsDirs(const vector<pair<string, vector<Expression*>>>& toRealign)
|
||||
{
|
||||
map<pair<string, string>, vector<vector<Expression*>>> groupedRules;
|
||||
for (auto& rule : toRealign)
|
||||
{
|
||||
auto currRule = rule.second;
|
||||
|
||||
string tRule = string(currRule[2]->unparse());
|
||||
string arrRule = string(currRule[1]->unparse());
|
||||
groupedRules[make_pair(tRule, arrRule)].push_back(currRule);
|
||||
}
|
||||
|
||||
map<pair<string, string>, vector<Expression*>> mergedGroupedRules;
|
||||
for (auto& rule : groupedRules)
|
||||
{
|
||||
SgExprListExp* mergedList = new SgExprListExp();
|
||||
for (int z = 0; z < rule.second.size(); ++z)
|
||||
{
|
||||
if (z == 0)
|
||||
mergedList->setLhs(rule.second[z][0]->GetOriginal());
|
||||
else
|
||||
mergedList->append(*rule.second[z][0]->GetOriginal());
|
||||
}
|
||||
vector<Expression*> medged = rule.second[0];
|
||||
medged[0] = new Expression(mergedList);
|
||||
mergedGroupedRules[rule.first] = medged;
|
||||
}
|
||||
|
||||
vector<pair<string, vector<Expression*>>> retVal;
|
||||
for (auto& elem : mergedGroupedRules)
|
||||
retVal.push_back(make_pair("", elem.second));
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//create realigns instead of full template redistribution
|
||||
pair<vector<Directive*>, vector<Directive*>>
|
||||
createRealignRules(Statement* st, const uint64_t regId, File *file, const string &templClone,
|
||||
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls, const set<DIST::Array*>& usedArrays,
|
||||
const pair<int, int> linesBeforeAfter)
|
||||
{
|
||||
vector<vector<pair<string, vector<Expression*>>>> optimizedRules(2);
|
||||
|
||||
for (int num = 0; num < 2; ++num)
|
||||
{
|
||||
for (auto &elemPair : sortArraysByName(usedArrays))
|
||||
{
|
||||
DIST::Array* elem = elemPair.second;
|
||||
if (elem->IsNotDistribute())
|
||||
continue;
|
||||
|
||||
auto realRef = getRealArrayRef(elem, regId, arrayLinksByFuncCalls);
|
||||
auto rules = realRef->GetAlignRulesWithTemplate(regId);
|
||||
auto links = realRef->GetLinksWithTemplate(regId);
|
||||
const auto &templ = realRef->GetTemplateArray(regId);
|
||||
if (templ == NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
vector<Expression*> realign = { NULL, NULL, NULL, NULL, NULL };
|
||||
SgVarRefExp *ref = new SgVarRefExp((SgSymbol*)elem->GetNameInLocationS(st));
|
||||
|
||||
realign[0] = new Expression(ref);
|
||||
SgExprListExp *list = new SgExprListExp();
|
||||
string base = "iEX";
|
||||
for (int z = 0; z < elem->GetDimSize(); ++z)
|
||||
{
|
||||
if (z == 0)
|
||||
list->setLhs(*new SgVarRefExp(findSymbolOrCreate(file, base + std::to_string(z))));
|
||||
else
|
||||
list->append(*new SgVarRefExp(findSymbolOrCreate(file, base + std::to_string(z))));
|
||||
}
|
||||
|
||||
realign[1] = new Expression(list);
|
||||
if (num == 0)
|
||||
realign[2] = new Expression(new SgArrayRefExp(*findSymbolOrCreate(file, templClone, new SgArrayType(*SgTypeInt()))));
|
||||
else
|
||||
realign[2] = new Expression(new SgArrayRefExp(*findSymbolOrCreate(file, templ->GetShortName(), new SgArrayType(*SgTypeInt()))));
|
||||
|
||||
vector<SgExpression*> templateRuleEx(templ->GetDimSize());
|
||||
std::fill(templateRuleEx.begin(), templateRuleEx.end(), (SgExpression*)NULL);
|
||||
for (int z = 0; z < elem->GetDimSize(); ++z)
|
||||
{
|
||||
if (links[z] != -1)
|
||||
{
|
||||
SgExpression *toSet = NULL;
|
||||
auto symb = new SgVarRefExp(*findSymbolOrCreate(file, base + std::to_string(z)));
|
||||
if (rules[z] == make_pair(1, 0))
|
||||
toSet = symb;
|
||||
else if (rules[z].second == 0)
|
||||
toSet = &(*new SgValueExp(rules[z].first) * *symb);
|
||||
else if (rules[z].first == 1)
|
||||
toSet = &(*symb + *new SgValueExp(rules[z].second));
|
||||
else
|
||||
toSet = &(*new SgValueExp(rules[z].first) * *symb + *new SgValueExp(rules[z].second));
|
||||
templateRuleEx[links[z]] = toSet;
|
||||
}
|
||||
}
|
||||
|
||||
for (int z = 0; z < templateRuleEx.size(); ++z)
|
||||
{
|
||||
SgExpression *toSet = NULL;
|
||||
if (templateRuleEx[z] == NULL)
|
||||
toSet = new SgVarRefExp(*findSymbolOrCreate(file, "*"));
|
||||
else
|
||||
toSet = templateRuleEx[z];
|
||||
((SgArrayRefExp*)realign[2]->GetOriginal())->addSubscript(*toSet);
|
||||
|
||||
}
|
||||
|
||||
optimizedRules[num].push_back(make_pair("", realign));
|
||||
}
|
||||
}
|
||||
|
||||
vector<vector<pair<string, vector<Expression*>>>> groupedOptRules(2);
|
||||
groupedOptRules[0] = groupRealignsDirs(optimizedRules[0]);
|
||||
groupedOptRules[1] = groupRealignsDirs(optimizedRules[1]);
|
||||
|
||||
pair<vector<Directive*>, vector<Directive*>> retVal;
|
||||
for (auto& elem : groupedOptRules[0])
|
||||
retVal.first.push_back(new CreatedDirective(elem.first, elem.second, linesBeforeAfter.first));
|
||||
for (auto& elem : groupedOptRules[1])
|
||||
retVal.second.push_back(new CreatedDirective(elem.first, elem.second, linesBeforeAfter.second));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static bool hasFunctionCall(SgExpression* ex)
|
||||
{
|
||||
bool ret = false;
|
||||
if (ex)
|
||||
{
|
||||
if (ex->variant() == FUNC_CALL)
|
||||
return true;
|
||||
ret |= hasFunctionCall(ex->lhs());
|
||||
ret |= hasFunctionCall(ex->rhs());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool splitToBase(SgExpression *ex, pair<SgExpression*, int> &splited)
|
||||
{
|
||||
bool res = true;
|
||||
if (hasFunctionCall(ex))
|
||||
return false;
|
||||
|
||||
if (ex->variant() == VAR_REF || ex->variant() == ARRAY_REF || ex->variant() == MULT_OP)
|
||||
splited = make_pair(ex, 0);
|
||||
else
|
||||
{
|
||||
if (ex->variant() == SUBT_OP || ex->variant() == ADD_OP)
|
||||
{
|
||||
int minus = (ex->variant() == ADD_OP) ? 1 : -1;
|
||||
if (ex->rhs())
|
||||
{
|
||||
int err, val;
|
||||
err = CalculateInteger(ex->rhs(), val);
|
||||
if (err == 0)
|
||||
{
|
||||
const int nextEx = ex->lhs()->variant();
|
||||
if (nextEx == VAR_REF || nextEx == ARRAY_REF || nextEx == MULT_OP)
|
||||
splited = make_pair(ex->lhs(), minus * val);
|
||||
else if (nextEx == SUBT_OP || nextEx == ADD_OP)
|
||||
{
|
||||
pair<SgExpression*, int> splitedNext;
|
||||
bool res = splitToBase(ex->lhs(), splitedNext);
|
||||
if (res == false)
|
||||
return false;
|
||||
else
|
||||
splited = make_pair(splitedNext.first, minus * val + splitedNext.second);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static void analyzeRightPart(SgExpression *ex, map<DIST::Array*, vector<pair<bool, map<string, pair<int, int>>>>> &rightValues,
|
||||
const map<DIST::Array*, vector<bool>> &dimsNotMatch)
|
||||
{
|
||||
if (ex)
|
||||
{
|
||||
if (ex->variant() == ARRAY_REF)
|
||||
{
|
||||
const std::string name = ex->symbol()->identifier();
|
||||
for (auto &elem : dimsNotMatch)
|
||||
{
|
||||
if (elem.first->GetShortName() == name)
|
||||
{
|
||||
int idx = 0;
|
||||
for (auto expr = ex->lhs(); expr; expr = expr->rhs(), ++idx)
|
||||
{
|
||||
if (elem.second[idx])
|
||||
{
|
||||
int err, val;
|
||||
err = CalculateInteger(expr->lhs(), val);
|
||||
if (err == 0)
|
||||
{
|
||||
if (rightValues[elem.first][idx].first)
|
||||
{
|
||||
auto it = rightValues[elem.first][idx].second.find("");
|
||||
if (it == rightValues[elem.first][idx].second.end())
|
||||
rightValues[elem.first][idx].second[""] = make_pair(val, val);
|
||||
else
|
||||
{
|
||||
it->second.first = std::min(it->second.first, val);
|
||||
it->second.second = std::max(it->second.second, val);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rightValues[elem.first][idx].first = true;
|
||||
rightValues[elem.first][idx].second[""] = make_pair(val, val);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pair<SgExpression*, int> splited;
|
||||
bool result = splitToBase(expr->lhs(), splited);
|
||||
if (result)
|
||||
{
|
||||
if (rightValues[elem.first][idx].first)
|
||||
{
|
||||
auto key = string(splited.first->unparse());
|
||||
auto itS = rightValues[elem.first][idx].second.find(key);
|
||||
if (itS == rightValues[elem.first][idx].second.end())
|
||||
itS = rightValues[elem.first][idx].second.insert(itS, make_pair(key, make_pair(splited.second, splited.second)));
|
||||
else
|
||||
{
|
||||
itS->second.first = std::min(itS->second.first, splited.second);
|
||||
itS->second.second = std::max(itS->second.second, splited.second);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rightValues[elem.first][idx].first = true;
|
||||
rightValues[elem.first][idx].second[string(splited.first->unparse())] = make_pair(splited.second, splited.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
analyzeRightPart(ex->lhs(), rightValues, dimsNotMatch);
|
||||
analyzeRightPart(ex->rhs(), rightValues, dimsNotMatch);
|
||||
}
|
||||
}
|
||||
|
||||
static bool analyzeLeftPart(SgExpression *left, const map<DIST::Array*, vector<bool>>& dimsNotMatch,
|
||||
map<DIST::Array*, vector<pair<bool, pair<string, int>>>> &leftValues, string &base)
|
||||
{
|
||||
const std::string name = left->symbol()->identifier();
|
||||
for (auto& elem : dimsNotMatch)
|
||||
{
|
||||
if (elem.first->GetShortName() == name)
|
||||
{
|
||||
int idx = 0;
|
||||
for (auto ex = left->lhs(); ex; ex = ex->rhs(), ++idx)
|
||||
{
|
||||
if (elem.second[idx])
|
||||
{
|
||||
int err, val;
|
||||
err = CalculateInteger(ex->lhs(), val);
|
||||
if (err == 0)
|
||||
{
|
||||
if (leftValues[elem.first][idx].first)
|
||||
{
|
||||
if (leftValues[elem.first][idx].second.first != "") // has non zero base expression
|
||||
return false;
|
||||
if (leftValues[elem.first][idx].second.second != val) // has conflict writes
|
||||
return false;
|
||||
}
|
||||
else
|
||||
leftValues[elem.first][idx] = make_pair(true, make_pair("", val));
|
||||
}
|
||||
else // WRITE OP can not recognized
|
||||
{
|
||||
pair<SgExpression*, int> splited;
|
||||
bool result = splitToBase(ex->lhs(), splited);
|
||||
if (result == false)
|
||||
return false;
|
||||
if (leftValues[elem.first][idx].first)
|
||||
{
|
||||
// has conflict writes
|
||||
if (leftValues[elem.first][idx].second.first != string(splited.first->unparse()) ||
|
||||
leftValues[elem.first][idx].second.second != splited.second)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
base = string(splited.first->unparse());
|
||||
leftValues[elem.first][idx] = make_pair(true, make_pair(base, splited.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool analyzeLoopBody(LoopGraph* loopV,
|
||||
map<DIST::Array*, vector<pair<bool, pair<string, int>>>>& leftValues,
|
||||
map<DIST::Array*, vector<pair<bool, map<string, pair<int, int>>>>>& rightValues,
|
||||
string& base,
|
||||
const map<DIST::Array*, vector<bool>> &dimsNotMatch,
|
||||
const map<string, FuncInfo*>& mapFuncInfo)
|
||||
{
|
||||
SgStatement* loop = loopV->loop->GetOriginal();
|
||||
for (auto st = loop; st != loop->lastNodeOfStmt(); st = st->lexNext())
|
||||
{
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
{
|
||||
auto left = st->expr(0);
|
||||
if (left->variant() == ARRAY_REF)
|
||||
{
|
||||
bool ok = analyzeLeftPart(left, dimsNotMatch, leftValues, base);
|
||||
if (ok == false)
|
||||
return false;
|
||||
}
|
||||
analyzeRightPart(st->expr(1), rightValues, dimsNotMatch);
|
||||
}
|
||||
else if (st->variant() == PROC_STAT)
|
||||
{
|
||||
string name = st->symbol()->identifier();
|
||||
if (isIntrinsicFunctionName(name.c_str()) == 0)
|
||||
{
|
||||
//TODO: contains and modules
|
||||
auto it = mapFuncInfo.find(name);
|
||||
int z = 0;
|
||||
for (SgExpression* ex = st->expr(0); ex; ex = ex->rhs(), ++z)
|
||||
{
|
||||
if (ex->lhs()->variant() == ARRAY_REF)
|
||||
{
|
||||
bool ok = true;
|
||||
if (it == mapFuncInfo.end())
|
||||
ok = analyzeLeftPart(ex->lhs(), dimsNotMatch, leftValues, base);
|
||||
else
|
||||
{
|
||||
if (it->second->funcParams.isArgIn(z) && !it->second->funcParams.isArgOut(z))
|
||||
analyzeRightPart(ex->lhs(), rightValues, dimsNotMatch);
|
||||
else
|
||||
ok = analyzeLeftPart(ex->lhs(), dimsNotMatch, leftValues, base);
|
||||
}
|
||||
if (ok == false)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
analyzeRightPart(ex->lhs(), rightValues, dimsNotMatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
analyzeRightPart(st->expr(1), rightValues, dimsNotMatch);
|
||||
}
|
||||
}
|
||||
|
||||
//is OK ?
|
||||
return true;
|
||||
}
|
||||
|
||||
void createParallelDirs(File *file,
|
||||
map<string, vector<Directive*>>& createdDirectives,
|
||||
vector<Messages>& messages,
|
||||
const vector<LoopGraph*>& loopsInFile,
|
||||
const map<string, vector<FuncInfo*>>& allFuncInfo,
|
||||
const vector<ParallelRegion*>& parallelRegions,
|
||||
const map<LoopGraph*, void*>& depInfoForLoopGraph,
|
||||
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
|
||||
{
|
||||
const string file_name = file->filename();
|
||||
map<int, LoopGraph*> mapLoopsInFile;
|
||||
createMapLoopGraph(loopsInFile, mapLoopsInFile);
|
||||
|
||||
map<string, FuncInfo*> mapFuncInfo;
|
||||
createMapOfFunc(allFuncInfo, mapFuncInfo);
|
||||
|
||||
for (int z = 0; z < parallelRegions.size(); ++z)
|
||||
{
|
||||
vector<Directive*> toInsert;
|
||||
|
||||
const DataDirective& dataDirectives = parallelRegions[z]->GetDataDir();
|
||||
const vector<int>& currentVariant = parallelRegions[z]->GetCurrentVariant();
|
||||
DIST::GraphCSR<int, double, attrType>& reducedG = parallelRegions[z]->GetReducedGraphToModify();
|
||||
DIST::Arrays<int>& allArrays = parallelRegions[z]->GetAllArraysToModify();
|
||||
|
||||
auto& tmp = dataDirectives.distrRules;
|
||||
vector<pair<DIST::Array*, const DistrVariant*>> currentVar;
|
||||
|
||||
if (sharedMemoryParallelization == 0)
|
||||
{
|
||||
for (int z1 = 0; z1 < currentVariant.size(); ++z1)
|
||||
currentVar.push_back(make_pair(tmp[z1].first, &tmp[z1].second[currentVariant[z1]]));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& loop : mapLoopsInFile)
|
||||
{
|
||||
auto& rules = loop.second->getDataDir().distrRules;
|
||||
for (auto& rule : rules)
|
||||
currentVar.push_back(make_pair(rule.first, &rule.second[0]));
|
||||
}
|
||||
}
|
||||
|
||||
selectParallelDirectiveForVariant(file, parallelRegions[z], reducedG, allArrays, loopsInFile,
|
||||
mapLoopsInFile, mapFuncInfo, currentVar,
|
||||
toInsert, parallelRegions[z]->GetId(), arrayLinksByFuncCalls,
|
||||
depInfoForLoopGraph, messages);
|
||||
|
||||
if (toInsert.size() > 0)
|
||||
{
|
||||
auto it = createdDirectives.find(file_name);
|
||||
if (it == createdDirectives.end())
|
||||
createdDirectives.insert(it, make_pair(file_name, toInsert));
|
||||
else
|
||||
for (int m = 0; m < toInsert.size(); ++m)
|
||||
it->second.push_back(toInsert[m]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef PRINT_DIR_RESULT
|
||||
#undef FIRST
|
||||
#undef SECOND
|
||||
#undef THIRD
|
||||
63
Sapfor/_src/DirectiveProcessing/directive_creator.h
Normal file
63
Sapfor/_src/DirectiveProcessing/directive_creator.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Distribution/Distribution.h"
|
||||
#include "../Utils/errors.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "../Utils/types.h"
|
||||
|
||||
void createParallelDirectives(const std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>> &loopInfo,
|
||||
const std::vector<ParallelRegion*>& regions,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls,
|
||||
std::vector<Messages> &messagesForFile);
|
||||
|
||||
void selectParallelDirectiveForVariant(File* file,
|
||||
ParallelRegion* currReg,
|
||||
DIST::GraphCSR<int, double, attrType>& reducedG,
|
||||
DIST::Arrays<int>& allArrays,
|
||||
const std::vector<LoopGraph*>& loopGraph,
|
||||
const std::map<int, LoopGraph*>& mapLoopGraph,
|
||||
const std::map<std::string, FuncInfo*>& mapFuncInfo,
|
||||
const std::vector<std::pair<DIST::Array*, const DistrVariant*>>& distribution,
|
||||
std::vector<Directive*>& toInsert,
|
||||
const uint64_t regionId,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const std::map<LoopGraph*, void*>& depInfoForLoopGraph,
|
||||
std::vector<Messages>& messages);
|
||||
|
||||
void filterParallelDirectives(const std::map<std::string, std::vector<LoopGraph*>>& loopGraph,
|
||||
std::map<std::string, std::vector<Directive*>>& createdDirectives);
|
||||
|
||||
bool analyzeLoopBody(LoopGraph* loopV,
|
||||
std::map<DIST::Array*, std::vector<std::pair<bool, std::pair<std::string, int>>>>& leftValues,
|
||||
std::map<DIST::Array*, std::vector<std::pair<bool, std::map<std::string, std::pair<int, int>>>>>& rightValues,
|
||||
std::string& base,
|
||||
const std::map<DIST::Array*, std::vector<bool>>& dimsNotMatch,
|
||||
const std::map<std::string, FuncInfo*>& mapFuncInfo);
|
||||
|
||||
std::pair<std::vector<Directive*>, std::vector<Directive*>> createRealignRules(Statement* spStat, const uint64_t regId, File* file, const std::string& templClone,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const std::set<DIST::Array*>& usedArrays,
|
||||
const std::pair<int, int>);
|
||||
|
||||
DIST::Array* getRealArrayRef(DIST::Array* in, const uint64_t regId, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
|
||||
void shiftAlignRulesForTemplates(const std::set<DIST::Array*>& arrays, const uint64_t regId, DataDirective& dataDirectives, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
|
||||
void createShadowSpec(const std::map<std::string, std::vector<LoopGraph*>>& loopGraph, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, const std::set<DIST::Array*>& forArrays);
|
||||
|
||||
void addShadowFromAnalysis(ParallelDirective* dir, const std::map<DIST::Array*, ArrayInfo*>& currAccesses);
|
||||
|
||||
bool checkForConflict(const std::map<DIST::Array*, ArrayInfo*>& currAccesses,
|
||||
const LoopGraph* currentLoop,
|
||||
std::map<DIST::Array*, std::pair<int, std::pair<int, int>>, DIST::ArrayComparator>& arrayWriteAcc,
|
||||
const std::vector<std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>>& acrossInfo,
|
||||
std::set<DIST::Array*>& acrossOutArrays);
|
||||
|
||||
void createParallelDirs(File* file,
|
||||
std::map<std::string, std::vector<Directive*>>& createdDirectives,
|
||||
std::vector<Messages>& messages,
|
||||
const std::vector<LoopGraph*>& loopsInFile,
|
||||
const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo,
|
||||
const std::vector<ParallelRegion*>& parallelRegions,
|
||||
const std::map<LoopGraph*, void*>& depInfoForLoopGraph,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
2225
Sapfor/_src/DirectiveProcessing/directive_creator_base.cpp
Normal file
2225
Sapfor/_src/DirectiveProcessing/directive_creator_base.cpp
Normal file
File diff suppressed because it is too large
Load Diff
536
Sapfor/_src/DirectiveProcessing/directive_omp_parser.cpp
Normal file
536
Sapfor/_src/DirectiveProcessing/directive_omp_parser.cpp
Normal file
@@ -0,0 +1,536 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include "dvm.h"
|
||||
#include "directive_omp_parser.h"
|
||||
#include "directive_parser.h"
|
||||
|
||||
#include "../Utils/SgUtils.h"
|
||||
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using std::set;
|
||||
using std::string;
|
||||
|
||||
|
||||
void removeOmpDir(SgStatement* st)
|
||||
{
|
||||
char* lineS = st->comments();
|
||||
if (!lineS)
|
||||
return;
|
||||
|
||||
vector<string> split;
|
||||
splitString(lineS, '\n', split);
|
||||
|
||||
int idx = 0;
|
||||
for (auto& elem : split)
|
||||
{
|
||||
string line = elem;
|
||||
convertToLower(line);
|
||||
if (line.substr(0, 5) == "!$omp")
|
||||
lineS[idx + 1] = '_';
|
||||
else if (line.substr(0, 3) == "!$ ")
|
||||
lineS[idx + 1] = '_';
|
||||
idx += line.size() + 1; // with '\n'
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addToAttribute(SgStatement* st, int var, vector<SgExpression*> list)
|
||||
{
|
||||
if (list.size())
|
||||
{
|
||||
SgExprListExp* ex = new SgExprListExp();
|
||||
ex->setLhs(new SgExpression(var, makeExprList(list), NULL));
|
||||
SgStatement* toAdd = new SgStatement(SPF_ANALYSIS_DIR, NULL, NULL, ex, NULL, NULL);
|
||||
toAdd->setlineNumber(st->lineNumber());
|
||||
toAdd->setLocalLineNumber(SPF_OMP_DIR);
|
||||
|
||||
//filter
|
||||
if (var == ACC_PRIVATE_OP)
|
||||
{
|
||||
vector<SgExpression*> list_new;
|
||||
|
||||
auto attributes = getAttributes<SgStatement*, SgStatement*>(st, set<int>{SPF_ANALYSIS_DIR});
|
||||
set<string> privates;
|
||||
for (auto& attr : attributes)
|
||||
fillPrivatesFromComment(new Statement(attr), privates);
|
||||
|
||||
if (privates.size())
|
||||
{
|
||||
for (auto& elem : list)
|
||||
if (privates.find(elem->unparse()) == privates.end())
|
||||
list_new.push_back(elem);
|
||||
list = list_new;
|
||||
|
||||
if (!list.size())
|
||||
{
|
||||
__spf_print(1, "-- skip privates on line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (var == REDUCTION_OP)
|
||||
{
|
||||
auto attributes = getAttributes<SgStatement*, SgStatement*>(st, set<int>{SPF_ANALYSIS_DIR});
|
||||
map<string, set<string>> reduction;
|
||||
for (auto& attr : attributes)
|
||||
fillReductionsFromComment(new Statement(attr), reduction);
|
||||
|
||||
map<string, set<string>> reductionToAdd;
|
||||
fillReductionsFromComment(new Statement(toAdd), reductionToAdd);
|
||||
|
||||
vector<SgExpression*> list_new;
|
||||
if (reduction.size())
|
||||
{
|
||||
if (reduction == reductionToAdd)
|
||||
{
|
||||
__spf_print(1, "-- skip reduction on line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
|
||||
return;
|
||||
}
|
||||
|
||||
map<string, set<string>> reductionToAddNew;
|
||||
for (auto& redPair : reductionToAdd)
|
||||
{
|
||||
auto it = reduction.find(redPair.first);
|
||||
if (it == reduction.end())
|
||||
reductionToAddNew[redPair.first] = redPair.second;
|
||||
else
|
||||
{
|
||||
set<string> newVar;
|
||||
for (auto& var : redPair.second)
|
||||
{
|
||||
auto itVar = it->second.find(var);
|
||||
if (itVar == it->second.end())
|
||||
reductionToAddNew[redPair.first].insert(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!reductionToAddNew.size())
|
||||
{
|
||||
__spf_print(1, "-- skip reduction on line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
|
||||
return;
|
||||
}
|
||||
|
||||
if (reductionToAddNew != reductionToAdd)
|
||||
{
|
||||
list.clear();
|
||||
for (auto& redPair : reductionToAddNew)
|
||||
for (auto& var : redPair.second)
|
||||
list.push_back(new SgExpression(ARRAY_OP,
|
||||
new SgKeywordValExp(redPair.first.c_str()),
|
||||
new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ex = new SgExprListExp();
|
||||
ex->setLhs(new SgExpression(var, makeExprList(list), NULL));
|
||||
toAdd = new SgStatement(SPF_ANALYSIS_DIR, NULL, NULL, ex, NULL, NULL);
|
||||
|
||||
st->addAttribute(SPF_ANALYSIS_DIR, toAdd, sizeof(SgStatement));
|
||||
|
||||
if (var == ACC_PRIVATE_OP)
|
||||
__spf_print(1, "-- set private attribute to line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
|
||||
else if (var == REDUCTION_OP)
|
||||
__spf_print(1, "-- set reduction attribute to line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_write_in_do(SgStatement* st, const string& var)
|
||||
{
|
||||
checkNull(st, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (st->variant() != FOR_NODE)
|
||||
return false;
|
||||
|
||||
SgStatement* lastNode = st->lastNodeOfStmt();
|
||||
for (SgStatement* op = st->lexNext(); st != lastNode; st = st->lexNext())
|
||||
{
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
{
|
||||
SgExpression* ex = st->expr(0);
|
||||
if (ex->variant() == ARRAY_REF || ex->variant() == VAR_REF)
|
||||
if (var == ex->symbol()->identifier())
|
||||
return true;
|
||||
}
|
||||
else if (st->variant() == FOR_NODE)
|
||||
{
|
||||
if (var == isSgForStmt(st)->doName()->identifier())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<OmpDir> parseOmpInStatement(SgStatement* st, const set<string>& globalPriv, bool forDo)
|
||||
{
|
||||
vector<OmpDir> resultAll;
|
||||
|
||||
const char* lineS = st->comments();
|
||||
if (!lineS)
|
||||
return resultAll;
|
||||
|
||||
string comment(lineS);
|
||||
convertToLower(comment);
|
||||
|
||||
vector<string> split;
|
||||
splitString(comment, '\n', split);
|
||||
|
||||
for (int z = split.size() - 1; z >= 0; z--)
|
||||
{
|
||||
string line = split[z];
|
||||
|
||||
if (line.substr(0, 6) == "!$omp&")
|
||||
{
|
||||
if (z - 1 < 0)
|
||||
break;
|
||||
split[z - 1] += line.substr(6);
|
||||
split[z] = "";
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& line : split)
|
||||
{
|
||||
if (line.substr(0, 5) == "!$omp")
|
||||
{
|
||||
OmpDir result;
|
||||
|
||||
string line1 = "";
|
||||
int space = 0;
|
||||
int brake = 0;
|
||||
for (int z = 0; z < line.size(); ++z)
|
||||
{
|
||||
if (brake < 0)
|
||||
return vector<OmpDir>(); // error
|
||||
|
||||
if (brake == 0)
|
||||
{
|
||||
if (line[z] == ' ')
|
||||
space++;
|
||||
else
|
||||
space = 0;
|
||||
if ((line[z] == ' ' && space <= 1) || line[z] != ' ')
|
||||
line1 += line[z];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (line[z] != ' ')
|
||||
line1 += line[z];
|
||||
}
|
||||
|
||||
if (line[z] == '(')
|
||||
{
|
||||
while (line1.size() > 2 && line1[line1.size() - 2] == ' ')
|
||||
line1 = line1.erase(line1.size() - 2, 1);
|
||||
brake++;
|
||||
space = 0;
|
||||
}
|
||||
else if (line[z] == ')')
|
||||
brake--;
|
||||
}
|
||||
vector<string> lexems;
|
||||
splitString(line1, ' ', lexems);
|
||||
bool doLexem = false;
|
||||
bool end = false;
|
||||
bool parallel = false;
|
||||
bool privat = false;
|
||||
|
||||
for (auto& lexem : lexems)
|
||||
{
|
||||
if (lexem == "do")
|
||||
{
|
||||
doLexem = true;
|
||||
result.keys.insert(lexem);
|
||||
}
|
||||
if (lexem == "end")
|
||||
{
|
||||
end = true;
|
||||
result.keys.insert(lexem);
|
||||
}
|
||||
if (lexem == "parallel")
|
||||
{
|
||||
parallel = true;
|
||||
result.keys.insert(lexem);
|
||||
}
|
||||
if (lexem == "private")
|
||||
{
|
||||
privat = true;
|
||||
result.keys.insert(lexem);
|
||||
}
|
||||
}
|
||||
|
||||
if (privat == false)
|
||||
{
|
||||
if (forDo && doLexem)
|
||||
{
|
||||
vector<SgExpression*> list;
|
||||
for (auto& var : globalPriv)
|
||||
if (is_write_in_do(st, var))
|
||||
list.push_back(new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st))));
|
||||
|
||||
if (list.size())
|
||||
addToAttribute(st, ACC_PRIVATE_OP, list);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& lexem : lexems)
|
||||
{
|
||||
bool priv = lexem.substr(0, strlen("private(")) == "private(";
|
||||
bool threadpriv = lexem.substr(0, strlen("threadprivate(")) == "threadprivate(";
|
||||
bool red = lexem.substr(0, strlen("reduction(")) == "reduction(";
|
||||
if (priv || threadpriv)
|
||||
{
|
||||
vector<string> sublex;
|
||||
splitString(lexem, '(', sublex);
|
||||
if (sublex.size() == 2 && lexem.back() == ')')
|
||||
{
|
||||
splitString(sublex[1].erase(sublex[1].size() - 1), ',', sublex);
|
||||
|
||||
vector<SgExpression*> list;
|
||||
set<string> uniqList;
|
||||
for (auto& varG : globalPriv)
|
||||
uniqList.insert(varG);
|
||||
|
||||
for (auto& var : sublex)
|
||||
uniqList.insert(var);
|
||||
|
||||
for (auto& var : uniqList)
|
||||
{
|
||||
if (priv)
|
||||
{
|
||||
result.privVars.insert(var);
|
||||
list.push_back(new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st))));
|
||||
}
|
||||
else
|
||||
result.threadPrivVars.insert(var);
|
||||
}
|
||||
|
||||
if (forDo && doLexem && priv)
|
||||
addToAttribute(st, ACC_PRIVATE_OP, list);
|
||||
}
|
||||
}
|
||||
else if (red)
|
||||
{
|
||||
vector<string> sublex;
|
||||
splitString(lexem, '(', sublex);
|
||||
if (sublex.size() == 2 && lexem.back() == ')')
|
||||
{
|
||||
splitString(sublex[1].erase(sublex[1].size() - 1), ':', sublex);
|
||||
|
||||
vector<string> vars;
|
||||
vector<SgExpression*> list;
|
||||
splitString(sublex[1], ',', vars);
|
||||
string op = "";
|
||||
|
||||
if (sublex[0] == "+")
|
||||
op = "sum";
|
||||
else if (sublex[0] == "*")
|
||||
op = "prod";
|
||||
else if (sublex[0] == "max")
|
||||
op = "max";
|
||||
else if (sublex[0] == "min")
|
||||
op = "min";
|
||||
else if (sublex[0] == ".or." || sublex[0] == "or")
|
||||
op = "or";
|
||||
else if (sublex[0] == ".and." || sublex[0] == "and")
|
||||
op = "and";
|
||||
else if (sublex[0] == ".eqv." || sublex[0] == "eqv")
|
||||
op = "eqv";
|
||||
else if (sublex[0] == ".neqv." || sublex[0] == "neqv")
|
||||
op = "neqv";
|
||||
|
||||
if (op != "")
|
||||
{
|
||||
for (auto& var : vars)
|
||||
{
|
||||
result.redVars[sublex[0]].insert(var);
|
||||
list.push_back(new SgExpression(ARRAY_OP, new SgKeywordValExp(op.c_str()), new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st)))));
|
||||
}
|
||||
}
|
||||
|
||||
if (forDo && doLexem && op != "")
|
||||
addToAttribute(st, REDUCTION_OP, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resultAll.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
return resultAll;
|
||||
}
|
||||
|
||||
//TODO: need to use IR and RD for checking
|
||||
static void filterPrivates(OmpDir& dir)
|
||||
{
|
||||
if (dir.privVars.size() == 0)
|
||||
return;
|
||||
|
||||
for (auto st = dir.start; st != dir.end; st = st->lexNext())
|
||||
{
|
||||
vector<OmpDir> res;
|
||||
if (st != dir.start)
|
||||
{
|
||||
set<string> dummy;
|
||||
res = parseOmpInStatement(st, dummy);
|
||||
}
|
||||
|
||||
bool hasParallelDo = false;
|
||||
for (auto& dir : res)
|
||||
{
|
||||
if (dir.keys.find("parallel") != dir.keys.end() ||
|
||||
dir.keys.find("do") != dir.keys.end())
|
||||
{
|
||||
hasParallelDo = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (res.size() == 0 || !hasParallelDo)
|
||||
{
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
{
|
||||
if (st->expr(0))
|
||||
{
|
||||
string ref = st->expr(0)->symbol()->identifier();
|
||||
dir.privVars.erase(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static vector<OmpDir> findAllGlobalParallelRegions(SgStatement* stFunc)
|
||||
{
|
||||
vector<OmpDir> sections;
|
||||
|
||||
SgStatement* lastNode = stFunc->lastNodeOfStmt();
|
||||
for (auto st = stFunc; st != lastNode; st = st->lexNext())
|
||||
{
|
||||
if (st == NULL)
|
||||
{
|
||||
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
set<string> dummy;
|
||||
auto res = parseOmpInStatement(st, dummy);
|
||||
|
||||
for (auto& dir : res)
|
||||
{
|
||||
auto end = dir.keys.end();
|
||||
if (dir.keys.find("parallel") != end
|
||||
&& dir.keys.find("do") == end
|
||||
&& dir.keys.find("end") == end)
|
||||
{
|
||||
if (sections.size() && sections.back().end == NULL) // has open parallel region
|
||||
{
|
||||
__spf_print(1, "wrong omp directives placed on line %d\n", st->lineNumber());
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
sections.push_back(dir);
|
||||
sections.back().start = st;
|
||||
}
|
||||
else if (dir.keys.find("parallel") != end
|
||||
&& dir.keys.find("do") == end
|
||||
&& dir.keys.find("end") != end)
|
||||
{
|
||||
if (!sections.size())
|
||||
{
|
||||
__spf_print(1, "wrong omp directives placed on line %d\n", st->lineNumber());
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
sections.back().end = st;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& dir : sections)
|
||||
filterPrivates(dir);
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
static set<string> getGlobalPrivate(SgStatement* st, const vector<OmpDir>& globalParallelRegions)
|
||||
{
|
||||
set<string> globalPrivates;
|
||||
const int line = st->lineNumber();
|
||||
if (line > 0)
|
||||
{
|
||||
for (auto& reg : globalParallelRegions)
|
||||
{
|
||||
if (reg.start->lineNumber() <= line && line < reg.end->lineNumber())
|
||||
{
|
||||
if (reg.privVars.size())
|
||||
return reg.privVars;
|
||||
else
|
||||
return globalPrivates;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& reg : globalParallelRegions)
|
||||
{
|
||||
for (auto stF = reg.start; stF != reg.end; stF = stF->lexNext())
|
||||
{
|
||||
if (st == stF)
|
||||
{
|
||||
if (reg.privVars.size())
|
||||
return reg.privVars;
|
||||
else
|
||||
return globalPrivates;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return globalPrivates;
|
||||
}
|
||||
|
||||
void parseOmpDirectives(SgFile* file, vector<Messages>& currMessages)
|
||||
{
|
||||
int funcNum = file->numberOfFunctions();
|
||||
|
||||
for (int i = 0; i < funcNum; ++i)
|
||||
{
|
||||
SgStatement* st = file->functions(i);
|
||||
SgStatement* lastNode = st->lastNodeOfStmt();
|
||||
|
||||
vector<OmpDir> globalParallelRegions = findAllGlobalParallelRegions(st);
|
||||
|
||||
while (st != lastNode)
|
||||
{
|
||||
if (st == NULL)
|
||||
{
|
||||
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (st->variant() == FOR_NODE)
|
||||
{
|
||||
SgForStmt* currSt = (SgForStmt*)st;
|
||||
if (currSt->isEnddoLoop() == 0)
|
||||
{
|
||||
__spf_print(1, "wrong omp directives placed\n");
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
else
|
||||
parseOmpInStatement(st, getGlobalPrivate(st, globalParallelRegions), true);
|
||||
}
|
||||
st = st->lexNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
26
Sapfor/_src/DirectiveProcessing/directive_omp_parser.h
Normal file
26
Sapfor/_src/DirectiveProcessing/directive_omp_parser.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "../Utils/errors.h"
|
||||
|
||||
#define SPF_USER_DIR 777
|
||||
#define SPF_USER_DIR_COPY 999
|
||||
#define SPF_OMP_DIR 888
|
||||
|
||||
struct OmpDir
|
||||
{
|
||||
std::set<std::string> privVars;
|
||||
std::set<std::string> threadPrivVars;
|
||||
std::map<std::string, std::set<std::string>> redVars;
|
||||
std::set<std::string> keys;
|
||||
|
||||
SgStatement* start = NULL;
|
||||
SgStatement* end = NULL;
|
||||
};
|
||||
|
||||
void removeOmpDir(SgStatement* st);
|
||||
std::vector<OmpDir> parseOmpInStatement(SgStatement* st, const std::set<std::string>& globalPriv, bool forDo = false);
|
||||
void parseOmpDirectives(SgFile* file, std::vector<Messages>& currMessages);
|
||||
656
Sapfor/_src/DirectiveProcessing/directive_parser.cpp
Normal file
656
Sapfor/_src/DirectiveProcessing/directive_parser.cpp
Normal file
@@ -0,0 +1,656 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <locale>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <assert.h>
|
||||
|
||||
#include "directive_parser.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../LoopAnalyzer/loop_analyzer.h"
|
||||
#include "../Utils/AstWrapper.h"
|
||||
#include "../Utils/errors.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::set;
|
||||
using std::tuple;
|
||||
using std::map;
|
||||
using std::make_pair;
|
||||
using std::pair;
|
||||
|
||||
bool isSPF_NoInline(Statement *stIn)
|
||||
{
|
||||
if (stIn)
|
||||
{
|
||||
SgStatement *st = stIn->GetOriginal();
|
||||
for (auto &data : getAttributes<SgStatement*, SgStatement*>(st, set<int>{ SPF_TRANSFORM_DIR }))
|
||||
{
|
||||
SgExpression *exprList = data->expr(0);
|
||||
while (exprList)
|
||||
{
|
||||
if (exprList->lhs()->variant() == SPF_NOINLINE_OP)
|
||||
{
|
||||
//__spf_print(1, "found no inline\n");
|
||||
return true;
|
||||
}
|
||||
exprList = exprList->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static map<SgSymbol*, Symbol*> dictCreated;
|
||||
|
||||
static inline string getSymbol(const string& s) { return s; }
|
||||
static inline string getSymbol(SgSymbol* s) { return s->identifier(); }
|
||||
|
||||
static inline string getData(SgExpression *symb, string*, bool moduleNameAdd = false)
|
||||
{
|
||||
SgSymbol* base = symb->symbol();
|
||||
SgSymbol* symbOr = OriginalSymbol(symb->symbol());
|
||||
if (symbOr == base)
|
||||
return symbOr->identifier();
|
||||
else
|
||||
{
|
||||
SgStatement* scope = symbOr->scope();
|
||||
checkNull(scope, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
if (scope->variant() != MODULE_STMT)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
return string(scope->symbol()->identifier()) + "::" + symbOr->identifier();
|
||||
}
|
||||
}
|
||||
|
||||
static inline Expression* getData(SgExpression *symb, Expression**, bool moduleNameAdd = false)
|
||||
{
|
||||
return new Expression(symb);
|
||||
}
|
||||
|
||||
static inline Symbol* getData(SgExpression *symb, Symbol**, bool moduleNameAdd = false)
|
||||
{
|
||||
SgSymbol *symbOr = OriginalSymbol(symb->symbol());
|
||||
auto it = dictCreated.find(symbOr);
|
||||
if (it == dictCreated.end())
|
||||
it = dictCreated.insert(it, make_pair(symbOr, new Symbol(symbOr)));
|
||||
return it->second;
|
||||
}
|
||||
|
||||
template<typename fillType>
|
||||
void fillPrivatesFromComment(Statement *stIn, set<fillType> &privates, int type)
|
||||
{
|
||||
if (stIn)
|
||||
{
|
||||
SgStatement *st = stIn->GetOriginal();
|
||||
if (st->variant() == SPF_ANALYSIS_DIR)
|
||||
{
|
||||
SgExpression *exprList = st->expr(0);
|
||||
while (exprList)
|
||||
{
|
||||
const int var = exprList->lhs()->variant();
|
||||
if ( ((var == ACC_PRIVATE_OP || var == SPF_PROCESS_PRIVATE_OP) && type == -1) ||
|
||||
(var == ACC_PRIVATE_OP && var == type) ||
|
||||
(var == SPF_PROCESS_PRIVATE_OP && var == type) )
|
||||
{
|
||||
SgExpression *list = exprList->lhs()->lhs();
|
||||
while (list)
|
||||
{
|
||||
fillType *dummy = NULL;
|
||||
privates.insert(getData(list->lhs(), dummy));
|
||||
list = list->rhs();
|
||||
}
|
||||
break;
|
||||
}
|
||||
exprList = exprList->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void fillPrivatesFromComment(Statement *st, set<string> &privates, int type);
|
||||
template void fillPrivatesFromComment(Statement *st, set<Symbol*> &privates, int type);
|
||||
|
||||
//XXX: need to remove message and to add implementation
|
||||
extern map<string, vector<Messages>> SPF_messages;
|
||||
|
||||
//for simple reduction
|
||||
template<typename fillType>
|
||||
void fillReductionsFromComment(Statement *stIn, map<string, set<fillType>> &reduction, bool moduleNameAdd, int type)
|
||||
{
|
||||
bool error = false;
|
||||
if (stIn)
|
||||
{
|
||||
SgStatement *st = stIn->GetOriginal();
|
||||
if (st->variant() == type)
|
||||
{
|
||||
SgExpression* exprList = NULL;
|
||||
if (type == SPF_ANALYSIS_DIR)
|
||||
exprList = st->expr(0);
|
||||
else if (type == DVM_PARALLEL_ON_DIR)
|
||||
exprList = st->expr(1);
|
||||
|
||||
while (exprList)
|
||||
{
|
||||
if (exprList->lhs()->variant() == REDUCTION_OP)
|
||||
{
|
||||
SgExpression *list = exprList->lhs()->lhs();
|
||||
while (list)
|
||||
{
|
||||
SgExpression *currRed = list->lhs(); // with variant ARRAY_OP
|
||||
|
||||
fillType redSymb, *dummy = NULL;
|
||||
//minloc/maxloc
|
||||
if (currRed->rhs()->variant() == EXPR_LIST)
|
||||
redSymb = getData(currRed->rhs()->lhs(), dummy, moduleNameAdd);
|
||||
else
|
||||
{
|
||||
redSymb = getData(currRed->rhs(), dummy, moduleNameAdd);
|
||||
if (currRed->rhs()->variant() == ARRAY_REF)
|
||||
{
|
||||
SgExpression* ref = currRed->rhs();
|
||||
if (ref->lhs() != NULL || ref->rhs() != NULL)
|
||||
{
|
||||
//XXX
|
||||
std::wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Reduction by element of array '%s' is not supported", to_wstring(getSymbol(redSymb)).c_str());
|
||||
__spf_printToLongBuf(messageR, R182, to_wstring(getSymbol(redSymb)).c_str());
|
||||
|
||||
SPF_messages[current_file->filename()].push_back(Messages(ERROR, stIn->lineNumber(), messageR, messageE, 1059));
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
string oper = ((SgKeywordValExp *)(currRed->lhs()))->value();
|
||||
|
||||
auto it = reduction.find(oper);
|
||||
if (oper == "minloc" || oper == "maxloc")
|
||||
{
|
||||
//skip
|
||||
//__spf_print(1, " MAXLOC/MINLOC operation from SPF not supported yet, ignored\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (it == reduction.end())
|
||||
it = reduction.insert(it, make_pair(oper, set<fillType>()));
|
||||
it->second.insert(redSymb);
|
||||
}
|
||||
list = list->rhs();
|
||||
}
|
||||
}
|
||||
exprList = exprList->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
template void fillReductionsFromComment(Statement *st, map<string, set<string>> &reduction, bool, int);
|
||||
template void fillReductionsFromComment(Statement *st, map<string, set<Symbol*>> &reduction, bool, int);
|
||||
|
||||
//for min/max loc reduction
|
||||
template<typename fillType>
|
||||
void fillReductionsFromComment(Statement *stIn, map<string, set<tuple<fillType, fillType, int>>> &reduction, bool moduleNameAdd, int type)
|
||||
{
|
||||
if (stIn)
|
||||
{
|
||||
SgStatement *st = stIn->GetOriginal();
|
||||
if (st->variant() == type)
|
||||
{
|
||||
SgExpression* exprList = NULL;
|
||||
if (type == SPF_ANALYSIS_DIR)
|
||||
exprList = st->expr(0);
|
||||
else if (type == DVM_PARALLEL_ON_DIR)
|
||||
exprList = st->expr(1);
|
||||
|
||||
while (exprList)
|
||||
{
|
||||
if (exprList->lhs()->variant() == REDUCTION_OP)
|
||||
{
|
||||
SgExpression *list = exprList->lhs()->lhs();
|
||||
while (list)
|
||||
{
|
||||
SgExpression *currRed = list->lhs();
|
||||
|
||||
fillType redSymb, *dummy = NULL;
|
||||
//minloc/maxloc
|
||||
if (currRed->rhs()->variant() == EXPR_LIST)
|
||||
redSymb = getData(currRed->rhs()->lhs(), dummy, moduleNameAdd);
|
||||
else
|
||||
redSymb = getData(currRed->rhs(), dummy, moduleNameAdd);
|
||||
string oper = ((SgKeywordValExp *)(currRed->lhs()))->value();
|
||||
|
||||
auto it = reduction.find(oper);
|
||||
if (oper == "minloc" || oper == "maxloc")
|
||||
{
|
||||
fillType arraySymb = getData(currRed->rhs()->rhs()->lhs(), dummy);
|
||||
int dim = currRed->rhs()->rhs()->rhs()->lhs()->valueInteger();
|
||||
|
||||
if (it == reduction.end())
|
||||
it = reduction.insert(it, make_pair(oper, set<tuple<fillType, fillType, int>>()));
|
||||
it->second.insert(std::make_tuple(redSymb, arraySymb, dim));
|
||||
}
|
||||
else
|
||||
{
|
||||
//skip
|
||||
}
|
||||
list = list->rhs();
|
||||
}
|
||||
}
|
||||
exprList = exprList->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void fillReductionsFromComment(Statement *st, map<string, set<tuple<string, string, int>>> &reduction, bool, int);
|
||||
template void fillReductionsFromComment(Statement *st, map<string, set<tuple<Symbol*, Symbol*, int>>> &reduction, bool, int);
|
||||
|
||||
void fillParameterFromComment(Statement *stIn, vector<pair<Expression*, Expression*>> &assigns)
|
||||
{
|
||||
if (stIn)
|
||||
{
|
||||
SgStatement *st = stIn->GetOriginal();
|
||||
if (st->variant() == SPF_ANALYSIS_DIR)
|
||||
{
|
||||
SgExpression *exprList = st->expr(0);
|
||||
while (exprList)
|
||||
{
|
||||
if (exprList->lhs() && exprList->lhs()->variant() == SPF_PARAMETER_OP)
|
||||
{
|
||||
auto paramList = exprList->lhs()->lhs();
|
||||
while (paramList)
|
||||
{
|
||||
assigns.push_back(make_pair(new Expression(paramList->lhs()->lhs()), new Expression(paramList->lhs()->rhs())));
|
||||
paramList = paramList->rhs();
|
||||
}
|
||||
}
|
||||
exprList = exprList->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename fillType>
|
||||
static void fillShadowAcross(const int type, Statement *stIn, vector<pair<pair<fillType, string>, vector<pair<int, int>>>> &data, set<fillType> *corner = NULL)
|
||||
{
|
||||
if (stIn)
|
||||
{
|
||||
SgStatement *st = stIn->GetOriginal();
|
||||
for (int list = 0; list < 3; ++list)
|
||||
{
|
||||
SgExpression *exprList = st->expr(list);
|
||||
while (exprList)
|
||||
{
|
||||
if (exprList->lhs()->variant() == type)
|
||||
{
|
||||
SgExpression *listExp = exprList->lhs()->lhs();
|
||||
while (listExp)
|
||||
{
|
||||
SgExpression *list = listExp;
|
||||
bool needCornerAdd = false;
|
||||
if (list->lhs()->variant() == ARRAY_OP)
|
||||
{
|
||||
list = list->lhs();
|
||||
needCornerAdd = true;
|
||||
}
|
||||
|
||||
SgSymbol *symb = OriginalSymbol(list->lhs()->symbol());
|
||||
|
||||
fillType arrayName, *dummy = NULL;
|
||||
arrayName = getData(list->lhs(), dummy);
|
||||
bool cond = false;
|
||||
|
||||
if (corner && needCornerAdd)
|
||||
corner->insert(arrayName);
|
||||
|
||||
pair<pair<fillType, string>, vector<pair<int, int>>> *toAdd;
|
||||
for (int i = 0; i < data.size(); ++i)
|
||||
{
|
||||
if (data[i].first.first == arrayName)
|
||||
{
|
||||
toAdd = &data[i];
|
||||
cond = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cond)
|
||||
{
|
||||
auto uniqKey = getFromUniqTable(symb);
|
||||
data.push_back(make_pair(make_pair(arrayName, getShortName(uniqKey)), vector<pair<int, int>>()));
|
||||
toAdd = &data.back();
|
||||
}
|
||||
|
||||
SgExpression *listEx = list->lhs()->lhs();
|
||||
int idx = 0;
|
||||
while (listEx)
|
||||
{
|
||||
SgExpression *width = listEx->lhs();
|
||||
const int left = width->lhs()->valueInteger();
|
||||
const int right = width->rhs()->valueInteger();
|
||||
if (toAdd->second.size() <= idx)
|
||||
toAdd->second.push_back(make_pair(left, right));
|
||||
else
|
||||
{
|
||||
toAdd->second[idx].first = std::max(toAdd->second[idx].first, left);
|
||||
toAdd->second[idx].second = std::max(toAdd->second[idx].second, right);
|
||||
}
|
||||
idx++;
|
||||
listEx = listEx->rhs();
|
||||
}
|
||||
|
||||
listExp = listExp->rhs();
|
||||
}
|
||||
}
|
||||
exprList = exprList->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename fillType>
|
||||
void fillShadowAcrossFromComment(const int type, Statement *stIn, vector<pair<pair<fillType, string>, vector<pair<int, int>>>> &data)
|
||||
{
|
||||
if (stIn)
|
||||
if (stIn->GetOriginal()->variant() == SPF_PARALLEL_DIR)
|
||||
fillShadowAcross(type, stIn, data);
|
||||
}
|
||||
|
||||
template void fillShadowAcrossFromComment(const int type, Statement *st, vector<pair<pair<string, string>, vector<pair<int, int>>>> &data);
|
||||
template void fillShadowAcrossFromComment(const int type, Statement *st, vector<pair<pair<Symbol*, string>, vector<pair<int, int>>>> &data);
|
||||
|
||||
|
||||
template<typename fillType>
|
||||
void fillShadowAcrossFromParallel(const int type, Statement *stIn, vector<pair<pair<fillType, string>, vector<pair<int, int>>>> &data, set<fillType> &corner)
|
||||
{
|
||||
if (stIn)
|
||||
if (stIn->GetOriginal()->variant() == DVM_PARALLEL_ON_DIR)
|
||||
fillShadowAcross(type, stIn, data, &corner);
|
||||
}
|
||||
|
||||
template void fillShadowAcrossFromParallel(const int type, Statement *st, vector<pair<pair<string, string>, vector<pair<int, int>>>> &data, set<string> &corner);
|
||||
template void fillShadowAcrossFromParallel(const int type, Statement* st, vector<pair<pair<Symbol*, string>, vector<pair<int, int>>>>& data, set<Symbol*> &corner);
|
||||
|
||||
|
||||
template<typename fillType>
|
||||
void fillRemoteFromComment(Statement *stIn, map<pair<fillType, string>, Expression*> &remote, bool isFull, int type)
|
||||
{
|
||||
if (stIn)
|
||||
{
|
||||
SgStatement *st = stIn->GetOriginal();
|
||||
if (st->variant() == type)
|
||||
{
|
||||
SgExpression *exprList = NULL;
|
||||
if (type == SPF_PARALLEL_DIR || type == DVM_REMOTE_ACCESS_DIR)
|
||||
exprList = st->expr(0);
|
||||
else if (type == DVM_PARALLEL_ON_DIR)
|
||||
exprList = st->expr(1);
|
||||
|
||||
while (exprList)
|
||||
{
|
||||
if (exprList->lhs()->variant() == REMOTE_ACCESS_OP || type == DVM_REMOTE_ACCESS_DIR)
|
||||
{
|
||||
SgExpression *list;
|
||||
if (type == DVM_REMOTE_ACCESS_DIR)
|
||||
list = exprList;
|
||||
else
|
||||
list = exprList->lhs()->lhs();
|
||||
|
||||
while (list)
|
||||
{
|
||||
fillType arrayName, *dummy = NULL;
|
||||
arrayName = getData(list->lhs(), dummy);
|
||||
|
||||
char *str;
|
||||
if (list->lhs()->lhs())
|
||||
str = list->lhs()->lhs()->unparse();
|
||||
else
|
||||
str = "";
|
||||
|
||||
if (isFull)
|
||||
remote.insert(make_pair(make_pair(arrayName, string(str)), new Expression(list->lhs())));
|
||||
else
|
||||
{
|
||||
if (list->lhs()->lhs())
|
||||
remote.insert(make_pair(make_pair(arrayName, string(str)), new Expression(list->lhs()->lhs())));
|
||||
else
|
||||
remote.insert(make_pair(make_pair(arrayName, string(str)), new Expression(new SgExprListExp())));
|
||||
}
|
||||
list = list->rhs();
|
||||
}
|
||||
}
|
||||
|
||||
if (type == DVM_REMOTE_ACCESS_DIR)
|
||||
break;
|
||||
exprList = exprList->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void fillRemoteFromComment(Statement *st, map<pair<string, string>, Expression*> &remote, bool isFull, int type);
|
||||
template void fillRemoteFromComment(Statement *st, map<pair<Symbol*, string>, Expression*> &remote, bool isFull, int type);
|
||||
template void fillRemoteFromComment(Statement *st, map<pair<Expression*, string>, Expression*> &remote, bool isFull, int type);
|
||||
|
||||
void fillAcrossInfoFromDirectives(const LoopGraph *loopInfo, vector<pair<pair<string, string>, vector<pair<int, int>>>> &acrossInfo)
|
||||
{
|
||||
SgForStmt *currentLoop = (SgForStmt*)loopInfo->loop;
|
||||
for (auto &data : getAttributes<SgStatement*, SgStatement*>(currentLoop, set<int>{ SPF_ANALYSIS_DIR, SPF_PARALLEL_DIR, SPF_TRANSFORM_DIR }))
|
||||
fillShadowAcrossFromComment(ACROSS_OP, new Statement(data), acrossInfo);
|
||||
}
|
||||
|
||||
void fillFissionPrivatesExpansionFromComment(Statement *stIn, vector<string> &vars)
|
||||
{
|
||||
if (stIn)
|
||||
{
|
||||
SgStatement *st = stIn->GetOriginal();
|
||||
if (st->variant() == SPF_TRANSFORM_DIR)
|
||||
{
|
||||
SgExpression *exprList = st->expr(0);
|
||||
while (exprList)
|
||||
{
|
||||
if (exprList->lhs() && (exprList->lhs()->variant() == SPF_FISSION_OP || exprList->lhs()->variant() == SPF_EXPAND_OP))
|
||||
{
|
||||
SgExpression *list = exprList->lhs()->lhs();
|
||||
while (list)
|
||||
{
|
||||
if (list->lhs()->variant() == VAR_REF)
|
||||
vars.push_back(list->lhs()->symbol()->identifier());
|
||||
|
||||
list = list->rhs();
|
||||
}
|
||||
}
|
||||
exprList = exprList->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename fillType>
|
||||
void fillShrinkFromComment(Statement *stIn, vector<pair<fillType, vector<int>>> &varDims)
|
||||
{
|
||||
if (stIn)
|
||||
{
|
||||
SgStatement *st = stIn->GetOriginal();
|
||||
if (st->variant() == SPF_TRANSFORM_DIR)
|
||||
{
|
||||
SgExpression *exprList = st->expr(0);
|
||||
while (exprList)
|
||||
{
|
||||
if (exprList->lhs() && (exprList->lhs()->variant() == SPF_SHRINK_OP))
|
||||
{
|
||||
SgExpression *list = exprList->lhs()->lhs();
|
||||
while (list)
|
||||
{
|
||||
// get identifier
|
||||
fillType var, *dummy = NULL;
|
||||
var = getData(list->lhs(), dummy);
|
||||
|
||||
vector<int> dims;
|
||||
SgExpression *dimList = list->lhs()->lhs();
|
||||
while (dimList)
|
||||
{
|
||||
// filling dimensions
|
||||
dimList->lhs()->isInteger() ? dims.push_back(dimList->lhs()->valueInteger()) : dims.push_back(-1);
|
||||
dimList = dimList->rhs();
|
||||
}
|
||||
|
||||
varDims.push_back(make_pair(var, dims));
|
||||
|
||||
list = list->rhs();
|
||||
}
|
||||
}
|
||||
|
||||
exprList = exprList->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void fillShrinkFromComment(Statement *stIn, vector<pair<Symbol*, vector<int>>> &varDims);
|
||||
template void fillShrinkFromComment(Statement *stIn, vector<pair<string, vector<int>>> &varDims);
|
||||
|
||||
template<typename fillType>
|
||||
void fillCheckpointFromComment(Statement *stIn, map<int, Expression*> &clauses, set<fillType> &vars, set<fillType> &expt)
|
||||
{
|
||||
if (stIn)
|
||||
{
|
||||
SgStatement *st = stIn->GetOriginal();
|
||||
if (st->variant() == SPF_CHECKPOINT_DIR)
|
||||
{
|
||||
SgExpression *exprList= st->expr(0);
|
||||
while (exprList)
|
||||
{
|
||||
if (exprList->lhs())
|
||||
{
|
||||
SgExpression *toInsert = NULL;
|
||||
if (exprList->lhs()->variant() == SPF_INTERVAL_OP)
|
||||
toInsert = new SgExpression(EXPR_LIST, exprList->lhs(), NULL);
|
||||
else if (exprList->lhs()->variant() == SPF_FILES_COUNT_OP)
|
||||
toInsert = new SgExpression(EXPR_LIST, exprList->lhs()->lhs(), NULL);
|
||||
else
|
||||
toInsert = exprList->lhs()->lhs();
|
||||
auto it = clauses.find(exprList->lhs()->variant());
|
||||
if (it == clauses.end())
|
||||
it = clauses.insert(it, make_pair(exprList->lhs()->variant(), new Expression(toInsert)));
|
||||
else
|
||||
{
|
||||
auto expr = it->second->GetOriginal();
|
||||
while (expr && expr->rhs())
|
||||
expr = expr->rhs();
|
||||
expr->setRhs(toInsert);
|
||||
}
|
||||
if (exprList->lhs()->variant() == SPF_VARLIST_OP ||
|
||||
exprList->lhs()->variant() == SPF_EXCEPT_OP)
|
||||
{
|
||||
auto expr = exprList->lhs()->lhs();
|
||||
while (expr)
|
||||
{
|
||||
// get identifier
|
||||
fillType var, *dummy = NULL;
|
||||
var = getData(expr->lhs(), dummy);
|
||||
if (exprList->lhs()->variant() == SPF_VARLIST_OP)
|
||||
{
|
||||
auto it = vars.find(var);
|
||||
if (it == vars.end())
|
||||
vars.insert(var);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = expt.find(var);
|
||||
if (it == expt.end())
|
||||
expt.insert(var);
|
||||
}
|
||||
expr = expr->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
exprList = exprList->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void fillCheckpointFromComment(Statement *stIn, map<int, Expression*> &clauses, set<Symbol*> &vars, set<Symbol*> &expt);
|
||||
template void fillCheckpointFromComment(Statement *stIn, map<int, Expression*> &clauses, set<string> &vars, set<string> &expt);
|
||||
|
||||
void fillInfoFromDirectives(const LoopGraph *loopInfo, ParallelDirective *directive)
|
||||
{
|
||||
SgForStmt *currentLoop = (SgForStmt*)loopInfo->loop;
|
||||
for (auto &data : getAttributes<SgStatement*, SgStatement*>(currentLoop, set<int>{ SPF_ANALYSIS_DIR, SPF_PARALLEL_DIR, SPF_TRANSFORM_DIR }))
|
||||
{
|
||||
Statement *sData = new Statement(data);
|
||||
fillPrivatesFromComment(sData, directive->privates);
|
||||
fillReductionsFromComment(sData, directive->reduction, true);
|
||||
fillReductionsFromComment(sData, directive->reductionLoc, true);
|
||||
fillShadowAcrossFromComment(SHADOW_OP, sData, directive->shadowRenew);
|
||||
fillShadowAcrossFromComment(ACROSS_OP, sData, directive->across);
|
||||
|
||||
map<pair<Symbol*, string>, Expression*> remotes;
|
||||
fillRemoteFromComment(sData, remotes);
|
||||
for (auto& elem : remotes)
|
||||
{
|
||||
SgSymbol* symb = OriginalSymbol(elem.first.first->GetOriginal());
|
||||
auto uniqKey = getFromUniqTable(symb);
|
||||
|
||||
directive->remoteAccess[make_pair(make_pair(elem.first.first->GetOriginal()->identifier(), getShortName(uniqKey)), elem.first.second)] = new Expression(elem.second->GetOriginal());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fillInfoFromDirective(Statement* parallel_on, DvmDirective& directive)
|
||||
{
|
||||
Statement* sData = parallel_on;
|
||||
|
||||
fillReductionsFromComment(sData, directive.reduction, true, DVM_PARALLEL_ON_DIR);
|
||||
fillReductionsFromComment(sData, directive.reductionLoc, true, DVM_PARALLEL_ON_DIR);
|
||||
|
||||
fillShadowAcrossFromParallel(SHADOW_RENEW_OP, sData, directive.shadowRenew, directive.corners);
|
||||
fillShadowAcrossFromParallel(ACROSS_OP, sData, directive.across, directive.corners);
|
||||
|
||||
//TODO:
|
||||
/*map<pair<Symbol*, string>, Expression*> remotes;
|
||||
fillRemoteFromComment(sData, remotes, false, DVM_PARALLEL_ON_DIR);
|
||||
for (auto& elem : remotes)
|
||||
{
|
||||
SgSymbol* symb = OriginalSymbol(elem.first.first->GetOriginal());
|
||||
auto uniqKey = getFromUniqTable(symb);
|
||||
|
||||
directive.remoteAccess[make_pair(make_pair(elem.first.first->GetOriginal()->identifier(), getShortName(uniqKey)), elem.first.second)] = new Expression(elem.second->GetOriginal());
|
||||
}*/
|
||||
}
|
||||
|
||||
int getCoverPropertyFromComment(Statement* stIn)
|
||||
{
|
||||
if (stIn)
|
||||
{
|
||||
SgStatement* st = stIn->GetOriginal();
|
||||
if (st->variant() == SPF_ANALYSIS_DIR)
|
||||
{
|
||||
SgExpression* exprList = st->expr(0);
|
||||
while (exprList)
|
||||
{
|
||||
if (exprList->lhs() && exprList->lhs()->variant() == SPF_COVER_OP)
|
||||
{
|
||||
auto value = exprList->lhs()->lhs();
|
||||
if (value->isInteger())
|
||||
return value->valueInteger();
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
exprList = exprList->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
55
Sapfor/_src/DirectiveProcessing/directive_parser.h
Normal file
55
Sapfor/_src/DirectiveProcessing/directive_parser.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "../Utils/AstWrapper.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "../Distribution/DvmhDirective.h"
|
||||
|
||||
struct DvmDirective
|
||||
{
|
||||
std::set<Symbol*> corners;
|
||||
std::vector<std::pair<std::pair<Symbol*, std::string>, std::vector<std::pair<int, int>>>> shadowRenew, across;
|
||||
std::map<std::pair<std::pair<std::string, std::string>, std::string>, Expression*> remoteAccess;
|
||||
|
||||
std::map<std::string, std::set<Symbol*>> reduction;
|
||||
std::map<std::string, std::set<std::tuple<Symbol*, Symbol*, int>>> reductionLoc;
|
||||
};
|
||||
|
||||
bool isSPF_NoInline(Statement *stPrev);
|
||||
|
||||
template<typename fillType>
|
||||
void fillPrivatesFromComment(Statement *st, std::set<fillType> &privates, int type = -1);
|
||||
|
||||
template<typename fillType>
|
||||
void fillReductionsFromComment(Statement *st, std::map<std::string, std::set<fillType>> &reduction, bool moduleNameAdd = false, int type = SPF_ANALYSIS_DIR);
|
||||
|
||||
template<typename fillType>
|
||||
void fillReductionsFromComment(Statement *st, std::map<std::string, std::set<std::tuple<fillType, fillType, int>>> &reduction, bool moduleNameAdd = false, int type = SPF_ANALYSIS_DIR);
|
||||
|
||||
void fillParameterFromComment(Statement *st, std::vector<std::pair<Expression*, Expression*>> &assigns);
|
||||
|
||||
template<typename fillType>
|
||||
void fillShadowAcrossFromComment(const int type, Statement *st, std::vector<std::pair<std::pair<fillType, std::string>, std::vector<std::pair<int, int>>>> &data);
|
||||
|
||||
template<typename fillType>
|
||||
void fillShadowAcrossFromParallel(const int type, Statement *st, std::vector<std::pair<std::pair<fillType, std::string>, std::vector<std::pair<int, int>>>> &data, std::set<fillType> &corner);
|
||||
|
||||
template<typename fillType>
|
||||
void fillRemoteFromComment(Statement *st, std::map<std::pair<fillType, std::string>, Expression*> &remote, bool isFull = false, int type = SPF_PARALLEL_DIR);
|
||||
|
||||
void fillAcrossInfoFromDirectives(const LoopGraph *loopInfo, std::vector<std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>> &acrossInfo);
|
||||
void fillInfoFromDirectives(const LoopGraph *loopInfo, ParallelDirective *directive);
|
||||
void fillInfoFromDirective(Statement* parallel_on, DvmDirective& directive);
|
||||
|
||||
void fillFissionPrivatesExpansionFromComment(Statement *stIn, std::vector<std::string> &vars);
|
||||
|
||||
template<typename fillType>
|
||||
void fillShrinkFromComment(Statement *stIn, std::vector<std::pair<fillType, std::vector<int>>> &varDims);
|
||||
|
||||
template<typename fillType>
|
||||
void fillCheckpointFromComment(Statement *stIn, std::map<int, Expression*> &clauses, std::set<fillType> &vars, std::set<fillType> &expt);
|
||||
|
||||
int getCoverPropertyFromComment(Statement* stIn);
|
||||
2426
Sapfor/_src/DirectiveProcessing/insert_directive.cpp
Normal file
2426
Sapfor/_src/DirectiveProcessing/insert_directive.cpp
Normal file
File diff suppressed because it is too large
Load Diff
63
Sapfor/_src/DirectiveProcessing/insert_directive.h
Normal file
63
Sapfor/_src/DirectiveProcessing/insert_directive.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
SgStatement* createStatFromExprs(const std::vector<Expression*>& exprs);
|
||||
|
||||
void insertLoopTempalteDeclaration(SgFile* file, const DataDirective& dataDir,
|
||||
const std::vector<std::string>& distrRules, const std::vector<std::vector<dist>>& distrRulesSt,
|
||||
const DIST::Arrays<int>& allArrays,
|
||||
const bool extractDir, const uint64_t regionId);
|
||||
|
||||
void insertTempalteDeclarationToMainFile(SgFile* file, const DataDirective& dataDir,
|
||||
const std::map<std::string, std::string>& templateDeclInIncludes,
|
||||
const std::vector<std::string>& distrRules, const std::vector<std::vector<dist>>& distrRulesSt,
|
||||
const DIST::Arrays<int>& allArrays,
|
||||
const bool extractDir, const uint64_t regionId,
|
||||
const std::set<std::string>& includedToThisFile);
|
||||
|
||||
void insertDirectiveToFile(SgFile* file, const char* fin_name, const std::vector<Directive*>& toInsert, const bool extractDir, std::vector<Messages>& messagesForFile);
|
||||
|
||||
void insertDistributionToFile(SgFile* file, const char* fin_name, const DataDirective& dataDir,
|
||||
const std::set<std::string>& distrArrays, const std::vector<std::string>& distrRules,
|
||||
const std::vector<std::vector<dist>>& distrRulesSt,
|
||||
const std::vector<std::string>& alignRules,
|
||||
const std::map<std::string, std::vector<LoopGraph*>>& loopGraph,
|
||||
const DIST::Arrays<int>& allArrays,
|
||||
DIST::GraphCSR<int, double, attrType>& reducedG,
|
||||
std::map<std::string, std::map<int, std::set<std::string>>>& commentsToInclude,
|
||||
std::map<std::string, std::string>& templateDeclInIncludes,
|
||||
const bool extractDir, std::vector<Messages>& messagesForFile,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const std::map<std::string, FuncInfo*>& funcsInFile,
|
||||
const uint64_t regionId,
|
||||
const std::set<std::string>& allFileNames);
|
||||
|
||||
void insertShadowSpecToFile(SgFile* file, const char* fin_name, const std::set<std::string>& distrArrays,
|
||||
DIST::GraphCSR<int, double, attrType>& reducedG,
|
||||
std::map<std::string, std::map<int, std::set<std::string>>>& commentsToInclude,
|
||||
const bool extractDir, std::vector<Messages>& messagesForFile,
|
||||
const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays);
|
||||
|
||||
void insertDistributionToFile(const char* origFile, const char* outFile, const std::map<int, std::set<std::string>>& commentsToInclude);
|
||||
void removeDvmDirectives(SgFile* file, const bool toComment);
|
||||
|
||||
void insertDistributeDirsToParallelRegions(const std::vector<ParallelRegionLines>* currLines,
|
||||
const std::vector<Statement*>& reDistrRulesBefore,
|
||||
const std::vector<Statement*>& reDistrRulesAfter,
|
||||
const std::vector<Statement*>& reAlignRules);
|
||||
|
||||
void insertTemplateModuleUse(SgFile* file, const std::set<uint64_t>& regNum, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
void removeStatementsFromAllproject(const std::set<int>& variants);
|
||||
void correctTemplateModuleDeclaration(const std::string& folderName);
|
||||
|
||||
void insertParallelDirs(SgFile* file, bool extract,
|
||||
std::vector<Directive*>& createdDirectives,
|
||||
std::vector<Messages>& messages,
|
||||
std::map<std::string, std::string>& templateDeclInIncludes,
|
||||
std::map<std::string, std::map<int, std::set<std::string>>>& commentsToInclude,
|
||||
const std::vector<FuncInfo*>& callGraph,
|
||||
const std::vector<ParallelRegion*>& parallelRegions,
|
||||
const std::map<std::string, std::vector<LoopGraph*>>& loopGraph,
|
||||
const std::set<std::string>& allFileNames,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays,
|
||||
const std::map<DIST::Array*, std::tuple<int, std::string, std::string>>& tableOfUniqNamesByArray);
|
||||
1031
Sapfor/_src/DirectiveProcessing/remote_access.cpp
Normal file
1031
Sapfor/_src/DirectiveProcessing/remote_access.cpp
Normal file
File diff suppressed because it is too large
Load Diff
48
Sapfor/_src/DirectiveProcessing/remote_access.h
Normal file
48
Sapfor/_src/DirectiveProcessing/remote_access.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
struct RemoteRequest
|
||||
{
|
||||
LoopGraph* position;
|
||||
int dimNum;
|
||||
REMOTE_TYPE value;
|
||||
int currLine;
|
||||
int maxDimSize;
|
||||
|
||||
explicit RemoteRequest(LoopGraph* position, int dimNum, REMOTE_TYPE value, int currLine, int maxDimSize) :
|
||||
position(position), dimNum(dimNum), value(value), currLine(currLine), maxDimSize(maxDimSize)
|
||||
{ }
|
||||
};
|
||||
|
||||
std::map<std::string, ArrayRefExp*>
|
||||
createRemoteInParallel(const std::pair<LoopGraph*, const ParallelDirective*> under_dvm_dir,
|
||||
const DIST::Arrays<int> &allArrays,
|
||||
const std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>> &loopInfo,
|
||||
DIST::GraphCSR<int, double, attrType> &reducedG,
|
||||
const DataDirective &data,
|
||||
const std::vector<int> &currVar,
|
||||
std::vector<Messages> &messages,
|
||||
const uint64_t regionId,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls,
|
||||
const std::map<std::string, FuncInfo*>& funcMap);
|
||||
|
||||
void addRemoteLink(const LoopGraph* loop, const std::map<std::string, FuncInfo*>& funcMap, ArrayRefExp* expr, std::map<std::string, ArrayRefExp*>& uniqRemotes,
|
||||
const std::set<std::string>& remotesInParallel, std::set<ArrayRefExp*>& addedRemotes, const std::vector<std::string>& mapToLoop,
|
||||
std::vector<Messages>& messages, const int line, bool bindToLoopDistribution = true);
|
||||
|
||||
ArrayRefExp* createRemoteLink(const LoopGraph* currLoop, const DIST::Array* forArray);
|
||||
|
||||
std::vector<RemoteRequest>
|
||||
checkArrayRefInLoopForRemoteStatus(bool ifUnknownArrayAssignFound,
|
||||
int sumMatched,
|
||||
int numOfSubs,
|
||||
int maxMatched,
|
||||
int currLine,
|
||||
DIST::Array* currArray,
|
||||
std::vector<int>& wasFound,
|
||||
ArrayRefExp* arrayRef,
|
||||
std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>>& loopInfo,
|
||||
const std::vector<int>& matchedToDim,
|
||||
const std::map<int, LoopGraph*>& sortedLoopGraph,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const ParallelRegion* region,
|
||||
const std::vector<LoopGraph*>& parentLoops);
|
||||
772
Sapfor/_src/DirectiveProcessing/remote_access_base.cpp
Normal file
772
Sapfor/_src/DirectiveProcessing/remote_access_base.cpp
Normal file
@@ -0,0 +1,772 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <assert.h>
|
||||
|
||||
#include "../Distribution/Arrays.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "../ParallelizationRegions/ParRegions.h"
|
||||
#include "remote_access.h"
|
||||
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
using std::tuple;
|
||||
using std::map;
|
||||
using std::set;
|
||||
using std::make_pair;
|
||||
using std::make_tuple;
|
||||
using std::get;
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
|
||||
#define DEB 0
|
||||
|
||||
static set<string> fillRemotesInParallel(const ParallelDirective* dvm_dir)
|
||||
{
|
||||
set<string> remotesInParallel;
|
||||
for (auto& elem : dvm_dir->remoteAccess)
|
||||
remotesInParallel.insert(elem.first.first.first + "(" + elem.first.second + ")");
|
||||
return remotesInParallel;
|
||||
}
|
||||
|
||||
static void createRemoteInParallel(const pair<LoopGraph*, const ParallelDirective*>& under_dvm_dir,
|
||||
const set<DIST::Array*>& doneInLoops,
|
||||
const map<string, FuncInfo*>& funcMap,
|
||||
map<string, ArrayRefExp*>& uniqRemotes, vector<Messages>& messages,
|
||||
const DataDirective& data, const vector<int>& currVar, const uint64_t regionId,
|
||||
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
|
||||
{
|
||||
const set<DIST::Array*> usedArrays = under_dvm_dir.first->usedArrays;
|
||||
const set<DIST::Array*> usedArraysWrite = under_dvm_dir.first->usedArraysWrite;
|
||||
const set<string> remotesInParallel = fillRemotesInParallel(under_dvm_dir.second);
|
||||
set<ArrayRefExp*> addedRemotes;
|
||||
|
||||
for (auto& usedArr : usedArrays)
|
||||
{
|
||||
if (doneInLoops.find(usedArr) == doneInLoops.end() && usedArraysWrite.find(usedArr) == usedArraysWrite.end())
|
||||
{
|
||||
set<DIST::Array*> realRefs;
|
||||
getRealArrayRefs(usedArr, usedArr, realRefs, arrayLinksByFuncCalls);
|
||||
|
||||
bool isDistr = false;
|
||||
|
||||
for (auto& realRef : realRefs)
|
||||
{
|
||||
auto templ = realRef->GetTemplateArray(regionId);
|
||||
for (int z = 0; z < data.distrRules.size(); ++z)
|
||||
{
|
||||
if (templ == data.distrRules[z].first)
|
||||
{
|
||||
for (auto& elem : data.distrRules[z].second[currVar[z]].distRule)
|
||||
if (elem == BLOCK)
|
||||
isDistr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDistr)
|
||||
{
|
||||
vector<string> mapToLoop;
|
||||
for (int z = 0; z < usedArr->GetDimSize(); ++z)
|
||||
mapToLoop.push_back("");
|
||||
|
||||
//TODO: find all array refs
|
||||
addRemoteLink(under_dvm_dir.first, funcMap, createRemoteLink(under_dvm_dir.first, usedArr), uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, -1, false);
|
||||
__spf_print(DEB, "CRIP: %d, AFTER MAIN CHECK for arrray '%s'\n", __LINE__, usedArr->GetShortName().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createRemoteInParallel(const map<DIST::Array*, vector<ArrayOp>> remoteRegularReadsOfTopLoop,
|
||||
const pair<LoopGraph*, const ParallelDirective*> under_dvm_dir,
|
||||
const DIST::Arrays<int>& allArrays,
|
||||
const map<LoopGraph*, map<DIST::Array*, ArrayInfo*>>& loopInfo,
|
||||
DIST::GraphCSR<int, double, attrType>& reducedG,
|
||||
const DataDirective& data,
|
||||
const vector<int>& currVar,
|
||||
map<string, ArrayRefExp*>& uniqRemotes,
|
||||
vector<Messages>& messages,
|
||||
const uint64_t regionId,
|
||||
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
set<DIST::Array*>& doneInLoops,
|
||||
const map<string, FuncInfo*>& funcMap)
|
||||
{
|
||||
if (!under_dvm_dir.first || !under_dvm_dir.second)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
__spf_print(DEB, "createRemoteInParallel %d, for loop %d\n", __LINE__, under_dvm_dir.first->lineNum);
|
||||
set<ArrayRefExp*> addedRemotes;
|
||||
|
||||
auto it = loopInfo.find(under_dvm_dir.first);
|
||||
if (it == loopInfo.end())
|
||||
{
|
||||
if (under_dvm_dir.first->perfectLoop > 1)
|
||||
{
|
||||
pair<LoopGraph*, const ParallelDirective*> nextDir = under_dvm_dir;
|
||||
nextDir.first = under_dvm_dir.first->children[0];
|
||||
|
||||
createRemoteInParallel(remoteRegularReadsOfTopLoop, nextDir, allArrays, loopInfo, reducedG, data, currVar, uniqRemotes, messages, regionId, arrayLinksByFuncCalls, doneInLoops, funcMap);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const map<DIST::Array*, ArrayInfo*>& currInfo = it->second;
|
||||
const ParallelDirective* parDir = under_dvm_dir.second;
|
||||
|
||||
DIST::Array* arrayRefOnDir = parDir->arrayRef;
|
||||
set<DIST::Array*> realRefArrayOnDir;
|
||||
const set<string> remotesInParallel = fillRemotesInParallel(parDir);
|
||||
const LoopGraph* currLoop = under_dvm_dir.first;
|
||||
|
||||
|
||||
if (!arrayRefOnDir->IsTemplate())
|
||||
{
|
||||
getRealArrayRefs(arrayRefOnDir, arrayRefOnDir, realRefArrayOnDir, arrayLinksByFuncCalls);
|
||||
if (realRefArrayOnDir.size() != 1)
|
||||
{
|
||||
vector<vector<tuple<DIST::Array*, int, pair<int, int>>>> allRules(realRefArrayOnDir.size());
|
||||
int tmpIdx = 0;
|
||||
for (auto& array : realRefArrayOnDir)
|
||||
reducedG.GetAlignRuleWithTemplate(array, allArrays, allRules[tmpIdx++], regionId);
|
||||
|
||||
if (!isAllRulesEqual(allRules))
|
||||
{
|
||||
__spf_print(1, "not supported yet\n");
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
else
|
||||
arrayRefOnDir = *(realRefArrayOnDir.begin());
|
||||
}
|
||||
else
|
||||
arrayRefOnDir = *(realRefArrayOnDir.begin());
|
||||
}
|
||||
|
||||
// for all array accesses in loop
|
||||
for (auto& array : currInfo)
|
||||
{
|
||||
DIST::Array* arrayRef = array.first;
|
||||
if (!arrayRef)
|
||||
continue;
|
||||
doneInLoops.insert(arrayRef);
|
||||
|
||||
const ArrayInfo* currArrayInfo = array.second;
|
||||
|
||||
set<DIST::Array*> realArrayRef;
|
||||
getRealArrayRefs(arrayRef, arrayRef, realArrayRef, arrayLinksByFuncCalls);
|
||||
|
||||
for (auto& elem : realArrayRef)
|
||||
{
|
||||
arrayRef = elem;
|
||||
|
||||
// fill links between current array and array in parallel dir
|
||||
vector<int> links;
|
||||
if (arrayRef != arrayRefOnDir)
|
||||
links = findLinksBetweenArrays(arrayRef, arrayRefOnDir, regionId);
|
||||
else
|
||||
{
|
||||
links.resize(arrayRef->GetDimSize());
|
||||
for (int k = 0; k < arrayRef->GetDimSize(); ++k)
|
||||
links[k] = k;
|
||||
}
|
||||
|
||||
//fill info links with template
|
||||
auto linksWithTempl = arrayRef->GetLinksWithTemplate(regionId);
|
||||
auto alignRuleWithTempl = arrayRef->GetAlignRulesWithTemplate(regionId);
|
||||
|
||||
const DIST::Array* templArray = arrayRef->GetTemplateArray(regionId);
|
||||
if (!templArray)
|
||||
continue; // may be error?
|
||||
|
||||
DIST::Array* templRefOnDir = arrayRefOnDir;
|
||||
if (!templRefOnDir->IsTemplate())
|
||||
templRefOnDir = templRefOnDir->GetTemplateArray(regionId);
|
||||
|
||||
if (templArray != templRefOnDir) // different templates
|
||||
{
|
||||
doneInLoops.erase(array.first);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// fill distribute data variant
|
||||
const DistrVariant* distrVar = NULL;
|
||||
for (int k = 0; k < data.distrRules.size(); ++k)
|
||||
{
|
||||
if (data.distrRules[k].first == templArray)
|
||||
{
|
||||
distrVar = &data.distrRules[k].second[currVar[k]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!distrVar)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
// set new redistribute rule, if exist
|
||||
const DistrVariant* newDistVar = currLoop->getRedistributeRule(templArray);
|
||||
if (newDistVar)
|
||||
distrVar = newDistVar;
|
||||
|
||||
set<string> parallelVars;
|
||||
parallelVars.insert(parDir->parallel.begin(), parDir->parallel.end());
|
||||
|
||||
vector<string> mapToLoop;
|
||||
for (int i = 0; i < links.size(); ++i)
|
||||
{
|
||||
if (links[i] != -1 && linksWithTempl[i] != -1)
|
||||
{
|
||||
bool isCorrect = false;
|
||||
const bool isInParallel = parallelVars.find(parDir->on[links[i]].first) != parallelVars.end();
|
||||
if (distrVar->distRule[linksWithTempl[i]] == BLOCK)
|
||||
{
|
||||
if (parDir->on[links[i]].first != "*" && isInParallel)
|
||||
isCorrect = true;
|
||||
else
|
||||
isCorrect = false;
|
||||
}
|
||||
if (isCorrect)
|
||||
mapToLoop.push_back(parDir->on[links[i]].first);
|
||||
else
|
||||
mapToLoop.push_back("");
|
||||
}
|
||||
else
|
||||
mapToLoop.push_back("");
|
||||
}
|
||||
|
||||
// main check
|
||||
for (int i = 0; i < links.size(); ++i)
|
||||
{
|
||||
bool needToCheck = false;
|
||||
if (links[i] != -1 && linksWithTempl[i] != -1)
|
||||
{
|
||||
const bool isInParallel = parallelVars.find(parDir->on[links[i]].first) != parallelVars.end();
|
||||
if (distrVar->distRule[linksWithTempl[i]] == BLOCK)
|
||||
{
|
||||
if (parDir->on[links[i]].first != "*" && !isInParallel)
|
||||
needToCheck = false;
|
||||
else
|
||||
needToCheck = true;
|
||||
}
|
||||
}
|
||||
else if (linksWithTempl[i] != -1)
|
||||
{
|
||||
// if distributed and used in loop with out link with array on dir
|
||||
if (distrVar->distRule[linksWithTempl[i]] == BLOCK)
|
||||
{
|
||||
// check all unrecognized refs
|
||||
for (auto& unrec : currArrayInfo->arrayAccessUnrec)
|
||||
{
|
||||
if (addedRemotes.find(unrec.first) != addedRemotes.end())
|
||||
continue;
|
||||
else if (unrec.second.second[i] == REMOTE_TRUE)
|
||||
{
|
||||
addRemoteLink(currLoop, funcMap, unrec.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, unrec.second.first);
|
||||
__spf_print(DEB, "CRIP: %d, REMOTE_TRUE\n", __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
// check all regular refs
|
||||
for (auto& reg : currArrayInfo->arrayAccess)
|
||||
{
|
||||
if (addedRemotes.find(reg.first) != addedRemotes.end())
|
||||
continue;
|
||||
|
||||
if (arrayRef == arrayRefOnDir)
|
||||
continue;
|
||||
|
||||
addRemoteLink(currLoop, funcMap, reg.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, reg.second.first);
|
||||
__spf_print(DEB, "CRIP: %d, IRREG_REFS\n", __LINE__);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// check if current dimention is distributed
|
||||
if (needToCheck)
|
||||
{
|
||||
// check unregular acceses
|
||||
for (auto& unrec : currArrayInfo->arrayAccessUnrec)
|
||||
{
|
||||
if (addedRemotes.find(unrec.first) != addedRemotes.end())
|
||||
continue;
|
||||
|
||||
if (unrec.second.second[i] == REMOTE_TRUE)
|
||||
{
|
||||
addRemoteLink(currLoop, funcMap, unrec.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, unrec.second.first);
|
||||
__spf_print(DEB, "CRIP: %d, IRREG_REFS && REMOTE_TRUE\n", __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
// and check regular acceses
|
||||
for (auto& regAccess : currArrayInfo->arrayAccess)
|
||||
{
|
||||
if (addedRemotes.find(regAccess.first) != addedRemotes.end())
|
||||
continue;
|
||||
|
||||
if (arrayRef == arrayRefOnDir)
|
||||
continue;
|
||||
|
||||
//if has reads in more than one dim and it dims are dirstributed
|
||||
int countOfDimAcc = 0;
|
||||
for (int z = 0; z < linksWithTempl.size(); ++z)
|
||||
{
|
||||
bool distributed = false;
|
||||
if (linksWithTempl[z] != -1)
|
||||
distributed = (distrVar->distRule[linksWithTempl[z]] == BLOCK);
|
||||
|
||||
countOfDimAcc += ((regAccess.second.second[z].coefficients.size() != 0) && distributed) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (countOfDimAcc > 1 ||
|
||||
countOfDimAcc == 1 && parDir->on[links[i]].first == "*")
|
||||
{
|
||||
addRemoteLink(currLoop, funcMap, regAccess.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, regAccess.second.first);
|
||||
__spf_print(DEB, "CRIP: %d ---\n", __LINE__);
|
||||
continue;
|
||||
}
|
||||
|
||||
//if has distributed dim but loop maped to *
|
||||
if (parDir->on[links[i]].first == "*")
|
||||
{
|
||||
if (linksWithTempl[i] != -1)
|
||||
if (distrVar->distRule[linksWithTempl[i]] == BLOCK)
|
||||
{
|
||||
addRemoteLink(currLoop, funcMap, regAccess.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, regAccess.second.first);
|
||||
__spf_print(DEB, "CRIP: %d, NOT MAPPED\n", __LINE__);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//if this array has no map rules to current array and this dim is distributed
|
||||
if (currLoop->directiveForLoop)
|
||||
{
|
||||
if (currLoop->directiveForLoop->on[links[i]].first != "*")
|
||||
{
|
||||
if (regAccess.second.second[i].coefficients.size() == 0)
|
||||
{
|
||||
addRemoteLink(currLoop, funcMap, regAccess.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, regAccess.second.first);
|
||||
__spf_print(DEB, "CRIP: %d, ----\n", __LINE__);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check with loop alignment
|
||||
auto itRegRemote = remoteRegularReadsOfTopLoop.find(array.first);
|
||||
if (itRegRemote != remoteRegularReadsOfTopLoop.end())
|
||||
{
|
||||
bool wasAdd = false;
|
||||
for (auto& reads : regAccess.second.second[i].coefficients)
|
||||
{
|
||||
const pair<int, int>& currReadAcc = reads.first;
|
||||
for (auto& ref : itRegRemote->second[i].coefficients)
|
||||
{
|
||||
if (ref.first == currReadAcc)
|
||||
{
|
||||
addRemoteLink(currLoop, funcMap, regAccess.first, uniqRemotes, remotesInParallel, addedRemotes, mapToLoop, messages, regAccess.second.first);
|
||||
__spf_print(DEB, "CRIP: %d, MISS\n", __LINE__);
|
||||
wasAdd = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (wasAdd)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // main check
|
||||
}
|
||||
}
|
||||
|
||||
if (currLoop->perfectLoop > 1)
|
||||
{
|
||||
pair<LoopGraph*, const ParallelDirective*> nextDir = under_dvm_dir;
|
||||
nextDir.first = currLoop->children[0];
|
||||
|
||||
createRemoteInParallel(remoteRegularReadsOfTopLoop, nextDir, allArrays, loopInfo, reducedG, data, currVar, uniqRemotes, messages, regionId, arrayLinksByFuncCalls, doneInLoops, funcMap);
|
||||
}
|
||||
}
|
||||
|
||||
map<string, ArrayRefExp*>
|
||||
createRemoteInParallel(const pair<LoopGraph*, const ParallelDirective*> under_dvm_dir,
|
||||
const DIST::Arrays<int>& allArrays,
|
||||
const map<LoopGraph*, map<DIST::Array*, ArrayInfo*>>& loopInfo,
|
||||
DIST::GraphCSR<int, double, attrType>& reducedG,
|
||||
const DataDirective& data,
|
||||
const vector<int>& currVar,
|
||||
vector<Messages>& messages,
|
||||
const uint64_t regionId,
|
||||
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const map<string, FuncInfo*>& funcMap)
|
||||
{
|
||||
map<string, ArrayRefExp*> uniqRemotes;
|
||||
set<DIST::Array*> doneInLoops;
|
||||
|
||||
createRemoteInParallel(under_dvm_dir.first->remoteRegularReads, under_dvm_dir, allArrays, loopInfo, reducedG, data, currVar, uniqRemotes, messages, regionId, arrayLinksByFuncCalls, doneInLoops, funcMap);
|
||||
createRemoteInParallel(under_dvm_dir, doneInLoops, funcMap, uniqRemotes, messages, data, currVar, regionId, arrayLinksByFuncCalls);
|
||||
|
||||
return uniqRemotes;
|
||||
}
|
||||
|
||||
static void addInfoToMap(map<LoopGraph*, map<DIST::Array*, ArrayInfo*>>& loopInfo, LoopGraph* position, DIST::Array* array,
|
||||
ArrayRefExp* arrayRef, const int dimNum, const REMOTE_TYPE& value, const int currLine,
|
||||
const int maxDimSize, vector<RemoteRequest>& requests)
|
||||
{
|
||||
requests.push_back(RemoteRequest(position, dimNum, value, currLine, maxDimSize));
|
||||
|
||||
auto it = loopInfo.find(position);
|
||||
if (loopInfo.end() == it)
|
||||
it = loopInfo.insert(it, make_pair(position, map<DIST::Array*, ArrayInfo*>()));
|
||||
|
||||
auto it1 = it->second.find(array);
|
||||
if (it1 == it->second.end())
|
||||
it1 = it->second.insert(it1, make_pair(array, new ArrayInfo()));
|
||||
|
||||
auto it2 = it1->second->arrayAccessUnrec.find(arrayRef);
|
||||
if (it2 == it1->second->arrayAccessUnrec.end())
|
||||
{
|
||||
it2 = it1->second->arrayAccessUnrec.insert(it2, make_pair(arrayRef, make_pair(currLine, vector<REMOTE_TYPE>())));
|
||||
|
||||
it2->second.second.resize(maxDimSize);
|
||||
std::fill(it2->second.second.begin(), it2->second.second.end(), REMOTE_NONE);
|
||||
}
|
||||
|
||||
if (dimNum == -1)
|
||||
{
|
||||
for (int z = 0; z < it2->second.second.size(); ++z)
|
||||
it2->second.second[z] |= value;
|
||||
}
|
||||
else
|
||||
it2->second.second[dimNum] |= value;
|
||||
|
||||
if (value == REMOTE_TRUE)
|
||||
__spf_print(DEB, "RemoteAccess[%d]: true for dim %d and array %s, loop line %d\n", __LINE__, dimNum, array->GetShortName().c_str(), position->lineNum);
|
||||
}
|
||||
|
||||
static pair<DIST::Array*, const DistrVariant*>
|
||||
getDistrVariant(const vector<pair<DIST::Array*, vector<DistrVariant>>>& distrRules,
|
||||
DIST::Array* forTempl, const vector<int>& currentVariant)
|
||||
{
|
||||
pair<DIST::Array*, const DistrVariant*> currentVar;
|
||||
for (int z1 = 0; z1 < currentVariant.size(); ++z1)
|
||||
{
|
||||
if (distrRules[z1].first == forTempl)
|
||||
{
|
||||
currentVar = make_pair(distrRules[z1].first, &distrRules[z1].second[currentVariant[z1]]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!currentVar.first)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
return currentVar;
|
||||
}
|
||||
|
||||
// call this function for each array reference under loop(s)
|
||||
vector<RemoteRequest>
|
||||
checkArrayRefInLoopForRemoteStatus(bool ifUnknownArrayAssignFound,
|
||||
int sumMatched, // sum of matched dimensions of 'arrayRef' to each 'parentLoops'
|
||||
int numOfSubs, // number of subscriptions of 'arrayRef'
|
||||
int maxMatched, // maximum numbe of matched dimensions of 'arrayRef' to each 'parentLoops'
|
||||
int currLine, // current line in source code of 'arrayRef'
|
||||
DIST::Array* currArray, // DIST::Array of 'arrayRef'
|
||||
vector<int>& wasFoundForLoop, // size == 'parentLoops'.size(), init value -> 0, each position is sum of match dims count of 'arrayRef'
|
||||
ArrayRefExp* arrayRef, // current expression of array ref under all 'parentLoops',
|
||||
map<LoopGraph*, map<DIST::Array*, ArrayInfo*>>& loopInfo,
|
||||
const vector<int>& matchedToDim, // size == 'parentLoops'.size(), init value -> -1, each position is dimension of match 'arrayRef' for 'parentLoop'
|
||||
const map<int, LoopGraph*>& sortedLoopGraph,
|
||||
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const ParallelRegion* region,
|
||||
const vector<LoopGraph*>& parentLoops) // all loops which are associated with 'arrayRef'
|
||||
{
|
||||
vector<RemoteRequest> requests;
|
||||
if (sumMatched != parentLoops.size() && sumMatched == numOfSubs)
|
||||
{
|
||||
set<DIST::Array*> realArrayRefs;
|
||||
getRealArrayRefs(currArray, currArray, realArrayRefs, arrayLinksByFuncCalls);
|
||||
|
||||
bool ok = true;
|
||||
DIST::Array* templ = NULL;
|
||||
vector<int> alignCoefs;
|
||||
for (auto& real : realArrayRefs)
|
||||
{
|
||||
DIST::Array* curr = real->GetTemplateArray(region->GetId(), false);
|
||||
alignCoefs = real->GetLinksWithTemplate(region->GetId());
|
||||
|
||||
if (templ == NULL)
|
||||
templ = curr;
|
||||
else if (templ != curr)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
string debOutStr = "";
|
||||
char buf[256];
|
||||
sprintf(buf, "RemoteAccess[%d]: check aligns for '%s'\n", __LINE__, currArray->GetShortName().c_str());
|
||||
debOutStr += buf;
|
||||
|
||||
for (int z = 0; z < wasFoundForLoop.size(); ++z)
|
||||
{
|
||||
sprintf(buf, "RemoteAccess[%d]: check aligns %d == %d\n", __LINE__, z, wasFoundForLoop[z]);
|
||||
debOutStr += buf;
|
||||
}
|
||||
|
||||
for (int z = 0; z < matchedToDim.size(); ++z)
|
||||
{
|
||||
sprintf(buf, "RemoteAccess[%d]: matchedToDim[%d] = %d\n", __LINE__, z, matchedToDim[z]);
|
||||
debOutStr += buf;
|
||||
}
|
||||
|
||||
for (int l = 0; l < alignCoefs.size(); ++l)
|
||||
{
|
||||
sprintf(buf, "RemoteAccess[%d]: alignCoefs[%d] = %d\n", __LINE__, l, alignCoefs[l]);
|
||||
debOutStr += buf;
|
||||
}
|
||||
|
||||
//check array's alignment
|
||||
for (int z = 0; z < wasFoundForLoop.size() && ok; ++z)
|
||||
{
|
||||
auto it = sortedLoopGraph.find(parentLoops[z]->lineNum);
|
||||
if (it == sortedLoopGraph.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
|
||||
if (!templ)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
const DataDirective& dataDirectives = region->GetDataDir();
|
||||
const vector<int>& currentVariant = region->GetCurrentVariant();
|
||||
|
||||
pair<DIST::Array*, const DistrVariant*> currentVar = getDistrVariant(dataDirectives.distrRules, templ, currentVariant);
|
||||
|
||||
LoopGraph* loop = it->second;
|
||||
if (!loop->directiveForLoop)
|
||||
{
|
||||
if (wasFoundForLoop[z])
|
||||
{
|
||||
if (matchedToDim[z] != -1 && alignCoefs[matchedToDim[z]] != -1 &&
|
||||
currentVar.second->distRule[alignCoefs[matchedToDim[z]]] == distType::BLOCK)
|
||||
{
|
||||
ok = false;
|
||||
if (!ok)
|
||||
{
|
||||
__spf_print(DEB, "%s\n", debOutStr.c_str());
|
||||
__spf_print(DEB, "RemoteAccess[%d]: call addInfoMaps from aligns miss\n", __LINE__);
|
||||
__spf_print(DEB, "RemoteAccess[%d]: z = %d\n", __LINE__, z);
|
||||
addInfoToMap(loopInfo, parentLoops[z], currArray, arrayRef, matchedToDim[z], REMOTE_TRUE, currLine, numOfSubs, requests);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//apply redistribute
|
||||
if (loop->getRedistributeRule(currentVar.first) != NULL)
|
||||
currentVar.second = loop->getRedistributeRule(currentVar.first);
|
||||
|
||||
DIST::Array* loopT = loop->directiveForLoop->arrayRef;
|
||||
sprintf(buf, "RemoteAccess[%d]: z = %d, array '%s'\n", __LINE__, z, loopT->GetShortName().c_str());
|
||||
debOutStr += buf;
|
||||
|
||||
int dimToMap = -1;
|
||||
for (int z1 = 0; z1 < loopT->GetDimSize(); ++z1)
|
||||
if (loop->directiveForLoop->on[z1].first != "*")
|
||||
dimToMap = z1;
|
||||
|
||||
sprintf(buf, "RemoteAccess[%d]: z = %d, dimToMap = %d\n", __LINE__, z, dimToMap);
|
||||
debOutStr += buf;
|
||||
if (dimToMap != -1)
|
||||
{
|
||||
if (loopT != templ && !loopT->IsTemplate())
|
||||
{
|
||||
sprintf(buf, "RemoteAccess[%d]: z = %d, false check !=\n", __LINE__, z);
|
||||
debOutStr += buf;
|
||||
|
||||
DIST::Array* loopTempl = loopT->GetTemplateArray(region->GetId(), false);
|
||||
vector<int> loopAlignCoefs = loopT->GetLinksWithTemplate(region->GetId());
|
||||
|
||||
if (loopTempl == NULL)
|
||||
{
|
||||
set<DIST::Array*> tmpSet;
|
||||
getRealArrayRefs(loopT, loopT, tmpSet, arrayLinksByFuncCalls);
|
||||
|
||||
set<DIST::Array*> templates;
|
||||
for (auto& elem : tmpSet)
|
||||
{
|
||||
loopTempl = elem->GetTemplateArray(region->GetId(), false);
|
||||
loopAlignCoefs = elem->GetLinksWithTemplate(region->GetId());
|
||||
templates.insert(loopTempl);
|
||||
}
|
||||
|
||||
if (templates.size() != 1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
if (loopTempl)
|
||||
{
|
||||
sprintf(buf, "RemoteAccess[%d]: z = %d, array '%s'\n", __LINE__, z, loopTempl->GetShortName().c_str());
|
||||
debOutStr += buf;
|
||||
}
|
||||
|
||||
if (templ != loopTempl)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (loopAlignCoefs.size() == 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (loopAlignCoefs.size() <= dimToMap)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (loopAlignCoefs[dimToMap] == -1)
|
||||
{
|
||||
//TODO: need more tests for this case: prev bug => bugreport_1676461809
|
||||
/*if (loop->hasParalleDirectiveBefore())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
else*/
|
||||
continue;
|
||||
}
|
||||
else
|
||||
dimToMap = loopAlignCoefs[dimToMap];
|
||||
}
|
||||
else if (loopT != templ && loopT->IsTemplate())
|
||||
{
|
||||
bool isDistr = false;
|
||||
for (auto& elem : currentVar.second->distRule)
|
||||
if (elem == BLOCK)
|
||||
isDistr = true;
|
||||
|
||||
if (isDistr)
|
||||
{
|
||||
ok = false;
|
||||
__spf_print(DEB, "%s\n", debOutStr.c_str());
|
||||
__spf_print(DEB, "RemoteAccess[%d]: call addInfoMaps from template miss\n", __LINE__);
|
||||
__spf_print(DEB, "RemoteAccess[%d]: z = %d\n", __LINE__, z);
|
||||
addInfoToMap(loopInfo, parentLoops[z], currArray, arrayRef, matchedToDim[z], REMOTE_TRUE, currLine, numOfSubs, requests);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
sprintf(buf, "RemoteAccess[%d]: ** z = %d, dimToMap = %d\n", __LINE__, z, dimToMap);
|
||||
debOutStr += buf;
|
||||
|
||||
for (int z = 0; z < currentVar.second->distRule.size(); ++z)
|
||||
{
|
||||
sprintf(buf, "RemoteAccess[%d]: distRule[%d] = %d\n", __LINE__, z, currentVar.second->distRule[z]);
|
||||
debOutStr += buf;
|
||||
}
|
||||
|
||||
if (wasFoundForLoop[z])
|
||||
{
|
||||
if (matchedToDim[z] != -1 && currentVar.second->distRule[alignCoefs[matchedToDim[z]]] == distType::BLOCK)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
for (int l = 0; l < alignCoefs.size(); ++l)
|
||||
{
|
||||
if (alignCoefs[l] == dimToMap)
|
||||
found = true;
|
||||
}
|
||||
ok = found;
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
__spf_print(DEB, "%s\n", debOutStr.c_str());
|
||||
__spf_print(DEB, "RemoteAccess[%d]: call addInfoMaps from aligns miss\n", __LINE__);
|
||||
__spf_print(DEB, "RemoteAccess[%d]: z = %d\n", __LINE__, z);
|
||||
__spf_print(DEB, "RemoteAccess[%d]: dimToMap = %d\n", __LINE__, dimToMap);
|
||||
addInfoToMap(loopInfo, parentLoops[z], currArray, arrayRef, matchedToDim[z], REMOTE_TRUE, currLine, numOfSubs, requests);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool distrAny = false;
|
||||
bool distrAll = true;
|
||||
int dDim = -1;
|
||||
|
||||
for (int idx = 0; idx < alignCoefs.size(); ++idx)
|
||||
{
|
||||
if (currentVar.second->distRule[idx] == distType::BLOCK)
|
||||
{
|
||||
dDim = idx;
|
||||
distrAny = true;
|
||||
}
|
||||
else
|
||||
distrAll = false;
|
||||
}
|
||||
|
||||
|
||||
if (matchedToDim[z] == -1 && distrAny && !distrAll)
|
||||
{
|
||||
ok = false;
|
||||
if (!ok)
|
||||
{
|
||||
__spf_print(DEB, "%s\n", debOutStr.c_str());
|
||||
__spf_print(DEB, "RemoteAccess[%d]: call addInfoMaps from aligns miss\n", __LINE__);
|
||||
__spf_print(DEB, "RemoteAccess[%d]: z = %d\n", __LINE__, z);
|
||||
__spf_print(DEB, "RemoteAccess[%d]: dimToMap = %d\n", __LINE__, dimToMap);
|
||||
addInfoToMap(loopInfo, parentLoops[z], currArray, arrayRef, dDim, REMOTE_TRUE, currLine, numOfSubs, requests);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ok && currArray->GetDimSize() > 1)
|
||||
for (int z = 0; z < wasFoundForLoop.size(); ++z)
|
||||
wasFoundForLoop[z] = 1;
|
||||
}
|
||||
|
||||
if (ifUnknownArrayAssignFound)
|
||||
{
|
||||
if (sumMatched != numOfSubs ||
|
||||
maxMatched != 1 ||
|
||||
(sumMatched != parentLoops.size() && sumMatched != numOfSubs))
|
||||
{
|
||||
int local = 0;
|
||||
bool hasLimits = false;
|
||||
for (int i = 0; i < wasFoundForLoop.size(); ++i)
|
||||
{
|
||||
if (wasFoundForLoop[i] == 1)
|
||||
{
|
||||
auto itLoop = sortedLoopGraph.find(parentLoops[i]->lineNum);
|
||||
if (itLoop == sortedLoopGraph.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (itLoop->second->hasLimitsToParallel())
|
||||
hasLimits = true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < wasFoundForLoop.size(); ++i)
|
||||
{
|
||||
if (wasFoundForLoop[i] != 1)
|
||||
{
|
||||
for (int k = 0; k < numOfSubs; ++k)
|
||||
{
|
||||
if (hasLimits)
|
||||
{
|
||||
__spf_print(DEB, "RemoteAccess[%d]: call addInfoMaps from hasLimits\n", __LINE__);
|
||||
addInfoToMap(loopInfo, parentLoops[i], currArray, arrayRef, k, REMOTE_TRUE, currLine, numOfSubs, requests);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return requests;
|
||||
}
|
||||
1990
Sapfor/_src/DirectiveProcessing/shadow.cpp
Normal file
1990
Sapfor/_src/DirectiveProcessing/shadow.cpp
Normal file
File diff suppressed because it is too large
Load Diff
150
Sapfor/_src/DirectiveProcessing/shadow.h
Normal file
150
Sapfor/_src/DirectiveProcessing/shadow.h
Normal file
@@ -0,0 +1,150 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
struct FuncInfo;
|
||||
struct LoopGraph;
|
||||
struct ShadowNode;
|
||||
struct CommonBlock;
|
||||
|
||||
typedef enum node : int { PARALLEL_DIR = 0, FUNCTION_CALL, PROCEDURE_CALL, STOP, START, END } nodeType;
|
||||
|
||||
struct ShadowElement
|
||||
{
|
||||
std::vector<std::pair<int, int>> bounds;
|
||||
std::map<FuncInfo*, std::string> origNameByProc;
|
||||
bool corner;
|
||||
|
||||
ShadowElement() { }
|
||||
ShadowElement(const std::vector<std::pair<int, int>>& bounds,
|
||||
const std::pair<FuncInfo*, std::string>& origName,
|
||||
bool corner) : bounds(bounds), corner(corner)
|
||||
{
|
||||
origNameByProc[origName.first] = origName.second;
|
||||
}
|
||||
|
||||
bool operator==(const ShadowElement& left) const
|
||||
{
|
||||
return bounds == left.bounds && origNameByProc == left.origNameByProc && corner == left.corner;
|
||||
}
|
||||
};
|
||||
|
||||
struct NextNode
|
||||
{
|
||||
ShadowNode* shNode;
|
||||
std::set<DIST::Array*> writeTo;
|
||||
bool isBackWard;
|
||||
bool hasRealigns;
|
||||
|
||||
NextNode() { }
|
||||
|
||||
NextNode(ShadowNode* shNode, const std::set<DIST::Array*>& writeTo, bool hasRealigns = false)
|
||||
: shNode(shNode), writeTo(writeTo), isBackWard(false), hasRealigns(hasRealigns)
|
||||
{ }
|
||||
|
||||
bool operator==(const NextNode& left) const
|
||||
{
|
||||
return (shNode == left.shNode) && (writeTo == left.writeTo);
|
||||
}
|
||||
|
||||
bool operator<(const NextNode& left) const
|
||||
{
|
||||
return shNode < left.shNode;
|
||||
}
|
||||
};
|
||||
|
||||
struct PrevNode
|
||||
{
|
||||
ShadowNode* shNode;
|
||||
bool* isBackWard;
|
||||
bool* hasRealigns;
|
||||
|
||||
PrevNode() { }
|
||||
PrevNode(ShadowNode* shNode, bool* isBackWard = NULL, bool* hasRealigns = NULL)
|
||||
: shNode(shNode), isBackWard(isBackWard), hasRealigns(hasRealigns)
|
||||
{ }
|
||||
|
||||
bool operator==(const PrevNode& left) const
|
||||
{
|
||||
return shNode == left.shNode;
|
||||
}
|
||||
};
|
||||
|
||||
struct ShadowNode
|
||||
{
|
||||
void *info;
|
||||
nodeType type;
|
||||
|
||||
//file and line
|
||||
std::pair<FuncInfo*, int> location;
|
||||
|
||||
std::map<DIST::Array*, std::vector<ShadowElement>> shadows;
|
||||
std::map<DIST::Array*, std::vector<ShadowElement>> newShadows;
|
||||
|
||||
std::vector<NextNode> next;
|
||||
//std::vector<PrevNode> prev;
|
||||
|
||||
ShadowNode(void* info, nodeType type, FuncInfo* func, int line) : info(info), type(type), location(std::make_pair(func, line)) { }
|
||||
|
||||
void MoveShadow(const std::pair<DIST::Array*, std::vector<ShadowElement>>& shadowAdd)
|
||||
{
|
||||
for (auto& elem : shadowAdd.second)
|
||||
newShadows[shadowAdd.first].push_back(elem);
|
||||
}
|
||||
|
||||
void MergeNewShadowElements()
|
||||
{
|
||||
for (auto& elemByArray : newShadows)
|
||||
{
|
||||
ShadowElement newElems;
|
||||
for (int z = 0; z < elemByArray.second.size(); ++z)
|
||||
{
|
||||
if (z == 0)
|
||||
newElems = elemByArray.second[0];
|
||||
else
|
||||
{
|
||||
newElems.corner |= elemByArray.second[z].corner;
|
||||
for (auto& fElem : elemByArray.second[z].origNameByProc)
|
||||
newElems.origNameByProc[fElem.first] = fElem.second;
|
||||
int k = 0;
|
||||
for (auto& bound : elemByArray.second[z].bounds)
|
||||
{
|
||||
newElems.bounds[k].first = std::max(newElems.bounds[k].first, bound.first);
|
||||
newElems.bounds[k].second = std::max(newElems.bounds[k].second, bound.second);
|
||||
++k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (elemByArray.second.size())
|
||||
{
|
||||
elemByArray.second.clear();
|
||||
elemByArray.second.push_back(newElems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addNext(const NextNode& nextNode)
|
||||
{
|
||||
bool exist = false;
|
||||
for (int z = 0; z < next.size() && !exist; ++z)
|
||||
if (next[z] == nextNode)
|
||||
exist = true;
|
||||
|
||||
if (!exist)
|
||||
next.push_back(nextNode);
|
||||
}
|
||||
};
|
||||
|
||||
void GroupShadow(const std::map<std::string, std::vector<FuncInfo*>>& funcs,
|
||||
const std::map<std::string, std::vector<LoopGraph*>>& loops,
|
||||
const DIST::Arrays<int>& allArrays,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const std::map<std::string, CommonBlock*>& commonBlocks);
|
||||
|
||||
void clearAllocatedShadowNodes();
|
||||
void devourShadowByRemote(void* file, const std::map<std::string, FuncInfo*>& allFuncs, const std::vector<LoopGraph*>& loops, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
void transformShadowIfFull(void* file, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
2668
Sapfor/_src/DirectiveProcessing/spf_directive_preproc.cpp
Normal file
2668
Sapfor/_src/DirectiveProcessing/spf_directive_preproc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
236
Sapfor/_src/Distribution/Array.cpp
Normal file
236
Sapfor/_src/Distribution/Array.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
#include "Array.h"
|
||||
#include "../Utils/errors.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static vector<pair<int, int>> applyNewOrder(const vector<pair<int, int>>& in, const vector<int>& newOrder)
|
||||
{
|
||||
int countOfDepr = 0;
|
||||
for (int z = 0; z < in.size(); ++z)
|
||||
countOfDepr += (in[z].first == 0 && in[z].second == 0) ? 1 : 0;
|
||||
|
||||
if (newOrder.size() == 0)
|
||||
return in;
|
||||
if (newOrder.size() + countOfDepr != in.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
vector<pair<int, int>> tmp, retTmp(newOrder.size());
|
||||
for (int z = 0; z < in.size(); ++z)
|
||||
if (!(in[z].first == 0 && in[z].second == 0))
|
||||
tmp.push_back(in[z]);
|
||||
|
||||
for (int z = 0; z < newOrder.size(); ++z)
|
||||
retTmp[z] = tmp[newOrder[z]];
|
||||
|
||||
vector<pair<int, int>> retVal;
|
||||
for (int z = 0, z1 = 0; z < in.size(); ++z)
|
||||
if ((in[z].first == 0 && in[z].second == 0))
|
||||
retVal.push_back(in[z]);
|
||||
else
|
||||
retVal.push_back(retTmp[z1++]);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static vector<int> applyNewOrder(const vector<int> &in, const vector<int> &newOrder)
|
||||
{
|
||||
int countOfDepr = 0;
|
||||
for (int z = 0; z < in.size(); ++z)
|
||||
countOfDepr += (in[z] == -1) ? 1 : 0;
|
||||
|
||||
if (newOrder.size() == 0)
|
||||
return in;
|
||||
if (newOrder.size() + countOfDepr != in.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
vector<int> tmp, retTmp(newOrder.size());
|
||||
for (int z = 0; z < in.size(); ++z)
|
||||
if (in[z] != -1)
|
||||
tmp.push_back(in[z]);
|
||||
|
||||
for (int z = 0; z < newOrder.size(); ++z)
|
||||
retTmp[z] = tmp[newOrder[z]];
|
||||
|
||||
vector<int> retVal;
|
||||
for (int z = 0, z1 = 0; z < in.size(); ++z)
|
||||
if (in[z] == -1)
|
||||
retVal.push_back(in[z]);
|
||||
else
|
||||
retVal.push_back(retTmp[z1++]);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static vector<T> applyNewOrderS(const vector<T> &in, const vector<int> &newOrder)
|
||||
{
|
||||
vector<T> retVal(in.size());
|
||||
if (newOrder.size() == 0)
|
||||
return in;
|
||||
if (newOrder.size() != in.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (int z = 0; z < newOrder.size(); ++z)
|
||||
retVal[z] = in[newOrder[z]];
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
vector<pair<int, int>> TemplateLink::GetAlignRules() const
|
||||
{
|
||||
vector<pair<int, int>> retVal = alignRuleWithTemplate;
|
||||
if (templateArray == NULL)
|
||||
return retVal;
|
||||
|
||||
vector<int> newOrder = templateArray->GetNewTemplateDimsOrder();
|
||||
if (newOrder.size() == 0)
|
||||
return alignRuleWithTemplate;
|
||||
else
|
||||
return applyNewOrder(retVal, newOrder);
|
||||
}
|
||||
|
||||
vector<int> TemplateLink::GetLinks() const
|
||||
{
|
||||
vector<int> retVal = linkWithTemplate;
|
||||
if (templateArray == NULL)
|
||||
return retVal;
|
||||
|
||||
vector<int> newOrder = templateArray->GetNewTemplateDimsOrder();
|
||||
if (newOrder.size() == 0)
|
||||
return linkWithTemplate;
|
||||
else
|
||||
return applyNewOrder(retVal, newOrder);
|
||||
}
|
||||
|
||||
string TemplateLink::toString() const
|
||||
{
|
||||
string retVal = "";
|
||||
|
||||
retVal += "#" + to_string(linkWithTemplate.size());
|
||||
for (int i = 0; i < linkWithTemplate.size(); ++i)
|
||||
retVal += "#" + to_string(linkWithTemplate[i]);
|
||||
|
||||
retVal += "#" + to_string(alignRuleWithTemplate.size());
|
||||
for (int i = 0; i < alignRuleWithTemplate.size(); ++i)
|
||||
retVal += "#" + to_string(alignRuleWithTemplate[i].first) + "#" + to_string(alignRuleWithTemplate[i].second);
|
||||
|
||||
retVal += "#" + to_string((long long)templateArray);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void TemplateLink::AddRule(const int dimNum, int dimTempl, const pair<int, int>& rule, Array* templateArray_)
|
||||
{
|
||||
linkWithTemplate[dimNum] = dimTempl;
|
||||
alignRuleWithTemplate[dimNum] = rule;
|
||||
templateArray = templateArray_;
|
||||
}
|
||||
|
||||
const vector<pair<int, int>>& Array::GetSizes()
|
||||
{
|
||||
if (templateDimsOrder.size() == 0)
|
||||
return sizes;
|
||||
else
|
||||
{
|
||||
if (orderedSizes.size() == 0)
|
||||
orderedSizes = applyNewOrderS(sizes, templateDimsOrder);
|
||||
return orderedSizes;
|
||||
}
|
||||
}
|
||||
|
||||
const vector<pair<pair<Expression*, pair<int, int>>, pair<Expression*, pair<int, int>>>>&
|
||||
Array::GetSizesExpr()
|
||||
{
|
||||
if (templateDimsOrder.size() == 0)
|
||||
return sizesExpr;
|
||||
else
|
||||
{
|
||||
if (orderedSizesExpr.size() == 0)
|
||||
orderedSizesExpr = applyNewOrderS(sizesExpr, templateDimsOrder);
|
||||
return orderedSizesExpr;
|
||||
}
|
||||
}
|
||||
|
||||
void printArrayInfo(const string& file, const map<tuple<int, string, string>, pair<Array*, ArrayAccessInfo*>>& declaredArrays)
|
||||
{
|
||||
FILE* out = fopen(file.c_str(), "w");
|
||||
if (out == NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (auto& elem : declaredArrays)
|
||||
{
|
||||
Array* currA = elem.second.first;
|
||||
ArrayAccessInfo* info = elem.second.second;
|
||||
|
||||
fprintf(out, "Array '%s' (full name '%s'):\n", currA->GetShortName().c_str(), currA->GetName().c_str());
|
||||
auto loc = currA->GetLocation();
|
||||
string locN = "";
|
||||
if (loc.first == l_COMMON)
|
||||
locN = "COMMON ";
|
||||
else if (loc.first == l_MODULE)
|
||||
locN = "MODULE ";
|
||||
else if (loc.first == l_PARAMETER)
|
||||
locN = "PARAMETER of ";
|
||||
else if (loc.first == l_LOCAL)
|
||||
locN = "LOCAL of ";
|
||||
else if (loc.first == l_LOCAL_SAVE)
|
||||
locN = "LOCAL (save) of ";
|
||||
else if (loc.first == l_STRUCT)
|
||||
locN = "STRUCT ";
|
||||
else
|
||||
locN = "UNKN ";
|
||||
locN += "'" + loc.second + "'";
|
||||
|
||||
fprintf(out, " type: %s\n", locN.c_str());
|
||||
for (auto& byFile : info->GetAllAccessInfo())
|
||||
{
|
||||
fprintf(out, " FOR FILE '%s':\n", convertFileName(byFile.first.c_str()).c_str());
|
||||
for (auto& byLine : byFile.second)
|
||||
for (auto& onLine : byLine.second)
|
||||
fprintf(out, " %s\n", onLine.PrintInfo().c_str());
|
||||
}
|
||||
fprintf(out, "=============== \n\n");
|
||||
}
|
||||
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
void fixTypeOfArrayInfoWithCallGraph(map<tuple<int, string, string>, pair<Array*, ArrayAccessInfo*>>& declaredArrays,
|
||||
const map<string, FuncInfo*>& allFuncs)
|
||||
{
|
||||
for (auto& elem : declaredArrays)
|
||||
{
|
||||
ArrayAccessInfo* info = elem.second.second;
|
||||
info->checkAndUpdate(allFuncs);
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayAccessInfo::checkAndUpdate(const map<string, FuncInfo*>& allFuncs)
|
||||
{
|
||||
for (auto& byFile : accessPatterns)
|
||||
{
|
||||
for (auto& byLine : byFile.second)
|
||||
{
|
||||
for (auto& acc : byLine.second)
|
||||
{
|
||||
if (acc.underFunctionPar != -1)
|
||||
{
|
||||
auto it = allFuncs.find(acc.fName);
|
||||
if (it != allFuncs.end())
|
||||
{
|
||||
if (it->second->funcParams.isArgIn(acc.underFunctionPar) &&
|
||||
!it->second->funcParams.isArgOut(acc.underFunctionPar))
|
||||
{
|
||||
//switch to READ
|
||||
acc.type = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
812
Sapfor/_src/Distribution/Array.h
Normal file
812
Sapfor/_src/Distribution/Array.h
Normal file
@@ -0,0 +1,812 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include "DvmhDirectiveBase.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../Utils/errors.h"
|
||||
|
||||
class Symbol;
|
||||
class Expression;
|
||||
struct FuncInfo;
|
||||
|
||||
#define STRING std::string
|
||||
#define VECTOR std::vector
|
||||
#define PAIR std::pair
|
||||
#define MAP std::map
|
||||
#define SET std::set
|
||||
#define TO_STR std::to_string
|
||||
|
||||
#if __SPF
|
||||
extern int sharedMemoryParallelization;
|
||||
#endif
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
typedef enum distFlag : int { DISTR = 0, NO_DISTR, SPF_PRIV, IO_PRIV } distFlagType;
|
||||
typedef enum arrayLocation : int { l_LOCAL = 0, l_COMMON, l_MODULE, l_PARAMETER, l_STRUCT, l_LOCAL_SAVE } arrayLocType;
|
||||
|
||||
class Array;
|
||||
|
||||
class TemplateLink
|
||||
{
|
||||
private:
|
||||
VECTOR<int> linkWithTemplate;
|
||||
VECTOR<PAIR<int, int>> alignRuleWithTemplate;
|
||||
Array *templateArray;
|
||||
|
||||
public:
|
||||
TemplateLink(const int dimSize)
|
||||
{
|
||||
linkWithTemplate.resize(dimSize);
|
||||
alignRuleWithTemplate.resize(dimSize);
|
||||
for (int i = 0; i < dimSize; ++i)
|
||||
linkWithTemplate[i] = -1;
|
||||
templateArray = NULL;
|
||||
}
|
||||
|
||||
TemplateLink(const TemplateLink ©)
|
||||
{
|
||||
linkWithTemplate = copy.linkWithTemplate;
|
||||
alignRuleWithTemplate = copy.alignRuleWithTemplate;
|
||||
templateArray = copy.templateArray;
|
||||
}
|
||||
|
||||
Array* GetTemplateArray() const { return templateArray; }
|
||||
VECTOR<PAIR<int, int>> GetAlignRules() const;
|
||||
VECTOR<int> GetLinks() const;
|
||||
void AddRule(const int dimNum, int value, const PAIR<int, int> &rule, Array *templateArray_);
|
||||
STRING toString() const;
|
||||
};
|
||||
|
||||
class Array
|
||||
{
|
||||
private:
|
||||
unsigned id;
|
||||
STRING name;
|
||||
STRING shortName;
|
||||
int dimSize;
|
||||
int typeSize; // size of one element of array
|
||||
// calculated sizes
|
||||
VECTOR<PAIR<int, int>> sizes;
|
||||
// original sizes + shifts
|
||||
VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>> sizesExpr;
|
||||
|
||||
VECTOR<PAIR<int, int>> orderedSizes;
|
||||
VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>> orderedSizesExpr;
|
||||
|
||||
// template info by region
|
||||
MAP<uint64_t, TemplateLink*> templateInfo;
|
||||
bool isTemplFlag;
|
||||
bool isLoopArrayFlag;
|
||||
distFlag isNonDistribute;
|
||||
Symbol *declSymbol;
|
||||
STRING uniqKey;
|
||||
|
||||
// PAIR<FILE, LINE>
|
||||
SET<PAIR<STRING, int>> declPlaces;
|
||||
MAP<PAIR<STRING, int>, Symbol*> declPlacesSymbol;
|
||||
//file-> map[incFile, line] -> symbol
|
||||
MAP<STRING, MAP<PAIR<STRING, int>, Symbol*>> declPlacesSymbolByFile;
|
||||
|
||||
//TYPE: 0 - local, 1 - common, 2 - module, 3 - function parameter
|
||||
// PAIR<TYPE, NAME>
|
||||
PAIR<arrayLocation, STRING> locationPos;
|
||||
VECTOR<VECTOR<PAIR<int, int>>> allShadowSpecs;
|
||||
|
||||
SET<STRING> containsInRegions;
|
||||
|
||||
// file -> lines
|
||||
MAP<STRING, SET<int>> usagePlaces;
|
||||
|
||||
VECTOR<bool> mappedDims;
|
||||
VECTOR<bool> depracateToDistribute;
|
||||
|
||||
bool ompThreadPrivate;
|
||||
bool privateInLoop;
|
||||
bool inEquivalence;
|
||||
private:
|
||||
TemplateLink* getTemlateInfo(const uint64_t regionId, bool withCheck = false)
|
||||
{
|
||||
auto it = templateInfo.find(regionId);
|
||||
TemplateLink *currLink = NULL;
|
||||
if (it == templateInfo.end())
|
||||
{
|
||||
#if __SPF
|
||||
if (withCheck && sharedMemoryParallelization != 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
#endif
|
||||
currLink = new TemplateLink(dimSize);
|
||||
templateInfo[regionId] = currLink;
|
||||
}
|
||||
else
|
||||
currLink = it->second;
|
||||
return currLink;
|
||||
}
|
||||
|
||||
void GenUniqKey()
|
||||
{
|
||||
uniqKey = shortName + locationPos.second + TO_STR(dimSize);
|
||||
for (auto &place : declPlaces)
|
||||
uniqKey += place.first + TO_STR(place.second);
|
||||
}
|
||||
|
||||
//clones of template for realignes
|
||||
MAP<VECTOR<dist>, STRING> templateClones;
|
||||
VECTOR<int> templateDimsOrder;
|
||||
|
||||
public:
|
||||
Array()
|
||||
{
|
||||
isTemplFlag = false;
|
||||
isLoopArrayFlag = false;
|
||||
isNonDistribute = NO_DISTR;
|
||||
typeSize = 0;
|
||||
uniqKey = "";
|
||||
dimSize = 0;
|
||||
id = -1;
|
||||
declSymbol = NULL;
|
||||
ompThreadPrivate = false;
|
||||
privateInLoop = false;
|
||||
inEquivalence = false;
|
||||
}
|
||||
|
||||
Array(const STRING &name, const STRING &shortName, const int dimSize, const unsigned id,
|
||||
const STRING &declFile, const int declLine, const PAIR<arrayLocation, STRING> &locationPos,
|
||||
Symbol *declSymbol, bool inOmpThreadPriv, bool privateInLoop, bool inEquivalence,
|
||||
const VECTOR<STRING> ®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);
|
||||
depracateToDistribute.resize(dimSize);
|
||||
|
||||
for (int z = 0; z < dimSize; ++z)
|
||||
{
|
||||
sizes[z] = std::make_pair((int)INT_MAX, (int)INT_MIN);
|
||||
PAIR<int, int> initVal = std::make_pair(0, 0);
|
||||
sizesExpr[z] = std::make_pair(std::make_pair((Expression*)NULL, initVal), std::make_pair((Expression*)NULL, initVal));
|
||||
mappedDims[z] = false;
|
||||
depracateToDistribute[z] = false;
|
||||
}
|
||||
|
||||
GenUniqKey();
|
||||
for (auto ® : 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;
|
||||
depracateToDistribute = copy.depracateToDistribute;
|
||||
ompThreadPrivate = copy.ompThreadPrivate;
|
||||
privateInLoop = copy.privateInLoop;
|
||||
inEquivalence = copy.inEquivalence;
|
||||
}
|
||||
|
||||
bool RemoveUnpammedDims()
|
||||
{
|
||||
bool needToRemove = false;
|
||||
int countToRem = 0;
|
||||
for (int z = 0; z < dimSize; ++z)
|
||||
{
|
||||
if (!mappedDims[z] || depracateToDistribute[z])
|
||||
{
|
||||
needToRemove = true;
|
||||
countToRem++;
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needToRemove == false)
|
||||
return false;
|
||||
if (countToRem == dimSize)
|
||||
return true;
|
||||
|
||||
VECTOR<PAIR<int, int>> newSizes;
|
||||
VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>> newSizesExpr;
|
||||
VECTOR<bool> newMappedDims;
|
||||
VECTOR<bool> newDepr;
|
||||
|
||||
for (int z = 0; z < dimSize; ++z)
|
||||
{
|
||||
if (mappedDims[z] && !depracateToDistribute[z])
|
||||
{
|
||||
newSizes.push_back(sizes[z]);
|
||||
newSizesExpr.push_back(sizesExpr[z]);
|
||||
newMappedDims.push_back(mappedDims[z]);
|
||||
newDepr.push_back(depracateToDistribute[z]);
|
||||
}
|
||||
}
|
||||
|
||||
sizes = newSizes;
|
||||
sizesExpr = newSizesExpr;
|
||||
mappedDims = newMappedDims;
|
||||
depracateToDistribute = newDepr;
|
||||
dimSize = (int)sizes.size();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int GetDimSize() const { return dimSize; }
|
||||
const STRING GetName() const { return name; }
|
||||
const STRING GetShortName() const { return shortName; }
|
||||
const STRING GetNameInLocation(void* location) const;
|
||||
void* GetNameInLocationS(void* location) const;
|
||||
|
||||
unsigned GetId() const { return id; }
|
||||
void SetSizes(VECTOR<PAIR<int, int>> &_sizes, bool notCopyToExpr = false)
|
||||
{
|
||||
sizes = _sizes;
|
||||
if (!notCopyToExpr)
|
||||
{
|
||||
for (int i = 0; i < sizesExpr.size(); ++i)
|
||||
{
|
||||
sizesExpr[i].first.second.first = sizes[i].first;
|
||||
sizesExpr[i].second.second.first = sizes[i].second;
|
||||
}
|
||||
}
|
||||
}
|
||||
const VECTOR<PAIR<int, int>>& GetSizes();
|
||||
const VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>>& GetSizesExpr();
|
||||
void SetTemplateFlag(const bool templFlag) { isTemplFlag = templFlag; }
|
||||
bool IsTemplate() const { return isTemplFlag; }
|
||||
bool IsLoopArray() const { return isLoopArrayFlag; }
|
||||
bool IsArray() const { return !isTemplFlag && !isLoopArrayFlag; }
|
||||
void SetLoopArray(const bool flag) { isLoopArrayFlag = flag; }
|
||||
void SetSizesExpr(const VECTOR<PAIR<Expression*, Expression*>> &_sizesExpr)
|
||||
{
|
||||
for (int i = 0; i < _sizesExpr.size(); ++i)
|
||||
{
|
||||
sizesExpr[i].first.first = _sizesExpr[i].first;
|
||||
sizesExpr[i].second.first = _sizesExpr[i].second;
|
||||
}
|
||||
}
|
||||
|
||||
int AddLinkWithTemplate(const int dimNum, const int dimTempl, Array *templateArray_, const PAIR<int, int> &rule, const uint64_t regionId)
|
||||
{
|
||||
int err = 0;
|
||||
if (dimNum >= dimSize)
|
||||
err = -1;
|
||||
else
|
||||
{
|
||||
TemplateLink *currLink = getTemlateInfo(regionId, templateArray_ == NULL);
|
||||
currLink->AddRule(dimNum, dimTempl, rule, templateArray_);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
VECTOR<int> GetLinksWithTemplate(const uint64_t regionId)
|
||||
{
|
||||
TemplateLink *currLink = getTemlateInfo(regionId, true);
|
||||
return currLink->GetLinks();
|
||||
}
|
||||
|
||||
VECTOR<PAIR<int, int>> GetAlignRulesWithTemplate(const uint64_t regionId)
|
||||
{
|
||||
TemplateLink *currLink = getTemlateInfo(regionId, true);
|
||||
return currLink->GetAlignRules();
|
||||
}
|
||||
|
||||
bool HasTemplateInfo(const uint64_t regionId) const
|
||||
{
|
||||
auto it = templateInfo.find(regionId);
|
||||
return (it != templateInfo.end());
|
||||
}
|
||||
|
||||
void ChangeName(const STRING &newName)
|
||||
{
|
||||
auto pos = name.find(shortName);
|
||||
if (pos != STRING::npos)
|
||||
{
|
||||
name.erase(pos, shortName.size());
|
||||
shortName = newName;
|
||||
name += newName;
|
||||
}
|
||||
GenUniqKey();
|
||||
}
|
||||
|
||||
void ExtendDimSize(const int dim, const PAIR<int, int> &size)
|
||||
{
|
||||
/*if (size.first == size.second)
|
||||
return;*/
|
||||
|
||||
sizes[dim].first = std::min(sizes[dim].first, size.first);
|
||||
sizes[dim].second = std::max(sizes[dim].second, size.second);
|
||||
|
||||
PAIR<int, int> &left = sizesExpr[dim].first.second;
|
||||
PAIR<int, int> &right = sizesExpr[dim].second.second;
|
||||
|
||||
left.second = std::min(left.second, sizes[dim].first - left.first);
|
||||
right.second = std::max(right.second, sizes[dim].second - right.first);
|
||||
}
|
||||
void SetId(const unsigned newId) { id = newId; }
|
||||
|
||||
const SET<PAIR<STRING, int>>& GetDeclInfo() const { return declPlaces; }
|
||||
const MAP<PAIR<STRING, int>, Symbol*>& GetDeclInfoWithSymb() const { return declPlacesSymbol; }
|
||||
void AddDeclInfo(const PAIR<STRING, int> &declInfo, const SET<STRING>& allFilesInProj,
|
||||
const STRING& currFile, Symbol* symb = NULL)
|
||||
{
|
||||
declPlaces.insert(declInfo);
|
||||
if (symb)
|
||||
{
|
||||
declPlacesSymbol[declInfo] = symb;
|
||||
if (allFilesInProj.find(declInfo.first) == allFilesInProj.end()) // from include
|
||||
declPlacesSymbolByFile[currFile][declInfo] = symb;
|
||||
}
|
||||
GenUniqKey();
|
||||
}
|
||||
|
||||
//save request of shadow spec
|
||||
void ExtendShadowSpec(const VECTOR<PAIR<int, int>> &newSpec)
|
||||
{
|
||||
if (allShadowSpecs.size() == 0)
|
||||
allShadowSpecs.resize(dimSize);
|
||||
|
||||
const PAIR<int, int> zeroPair(0, 0);
|
||||
for (int i = 0; i < newSpec.size(); ++i)
|
||||
if (newSpec[i] != zeroPair)
|
||||
allShadowSpecs[i].push_back(newSpec[i]);
|
||||
}
|
||||
|
||||
//remove last requst of shadow spec
|
||||
void RemoveShadowSpec(const VECTOR<PAIR<int, int>> &delSpec)
|
||||
{
|
||||
int dimN = 0;
|
||||
for (auto &group : allShadowSpecs)
|
||||
{
|
||||
for (int i = 0; i < group.size(); ++i)
|
||||
{
|
||||
if (group[i] == delSpec[dimN])
|
||||
{
|
||||
group.erase(group.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
++dimN;
|
||||
}
|
||||
}
|
||||
|
||||
//construct shadow spec from all requests
|
||||
const VECTOR<PAIR<int, int>> GetShadowSpec() const
|
||||
{
|
||||
VECTOR<PAIR<int, int>> shadowSpec;
|
||||
shadowSpec.resize(dimSize);
|
||||
for (int i = 0; i < dimSize; ++i)
|
||||
shadowSpec[i] = std::make_pair(0, 0);
|
||||
|
||||
int dimN = 0;
|
||||
for (auto &group : allShadowSpecs)
|
||||
{
|
||||
for (auto &elem : group)
|
||||
{
|
||||
shadowSpec[dimN].first = std::max(shadowSpec[dimN].first, elem.first);
|
||||
shadowSpec[dimN].second = std::max(shadowSpec[dimN].second, elem.second);
|
||||
}
|
||||
++dimN;
|
||||
}
|
||||
return shadowSpec;
|
||||
}
|
||||
|
||||
void ClearShadowSpecs() { allShadowSpecs.clear(); }
|
||||
|
||||
STRING toString()
|
||||
{
|
||||
STRING retVal = "";
|
||||
retVal += TO_STR(id);
|
||||
retVal += "#" + name;
|
||||
retVal += "#" + shortName;
|
||||
retVal += "#" + TO_STR(dimSize);
|
||||
retVal += "#" + TO_STR(typeSize);
|
||||
retVal += "#" + TO_STR(isNonDistribute);
|
||||
|
||||
retVal += "#" + TO_STR(locationPos.first);
|
||||
retVal += "#" + locationPos.second;
|
||||
|
||||
retVal += "#" + TO_STR(sizes.size());
|
||||
for (int i = 0; i < sizes.size(); ++i)
|
||||
retVal += "#" + TO_STR(sizes[i].first) + "#" + TO_STR(sizes[i].second);
|
||||
|
||||
retVal += "#" + TO_STR(depracateToDistribute.size());
|
||||
for (int i = 0; i < depracateToDistribute.size(); ++i)
|
||||
retVal += "#" + TO_STR((int)depracateToDistribute[i]);
|
||||
|
||||
retVal += "#" + TO_STR(mappedDims.size());
|
||||
for (int i = 0; i < mappedDims.size(); ++i)
|
||||
retVal += "#" + TO_STR((int)mappedDims[i]);
|
||||
|
||||
retVal += "#" + TO_STR(templateInfo.size());
|
||||
for (auto it = templateInfo.begin(); it != templateInfo.end(); ++it)
|
||||
retVal += "#" + TO_STR(it->first) + it->second->toString();
|
||||
|
||||
retVal += "#" + TO_STR((int)isTemplFlag);
|
||||
retVal += "|" + TO_STR((int)isLoopArrayFlag);
|
||||
retVal += "|" + TO_STR(declPlaces.size());
|
||||
|
||||
for (auto &place : declPlaces)
|
||||
retVal += "|" + place.first + "|" + TO_STR(place.second);
|
||||
|
||||
retVal += "|" + TO_STR(containsInRegions.size());
|
||||
for (auto ® : containsInRegions)
|
||||
retVal += "|" + reg;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
Array* GetTemplateArray(const uint64_t regionId, bool withCheck = true)
|
||||
{
|
||||
TemplateLink *currLink = getTemlateInfo(regionId, withCheck);
|
||||
return currLink->GetTemplateArray();
|
||||
}
|
||||
|
||||
void SetDistributeFlag(const distFlag isNonDistribute_) { isNonDistribute = isNonDistribute_; }
|
||||
bool IsNotDistribute() const { return (isNonDistribute == DISTR) ? false : true; }
|
||||
distFlag GetDistributeFlagVal() const { return isNonDistribute; }
|
||||
|
||||
void ChangeLocation(arrayLocation loc, const STRING &name)
|
||||
{
|
||||
locationPos = std::make_pair(loc, name);
|
||||
}
|
||||
|
||||
void SetLocation(arrayLocation loc, const STRING &name)
|
||||
{
|
||||
ChangeLocation(loc, name);
|
||||
GenUniqKey();
|
||||
}
|
||||
PAIR<arrayLocation, STRING> GetLocation() const { return locationPos; }
|
||||
|
||||
Symbol* GetDeclSymbol(const STRING& file, const PAIR<int, int>& range, const SET<STRING>& allFilesInProj) const
|
||||
{
|
||||
if (!IsArray() || locationPos.first != l_COMMON)
|
||||
return declSymbol;
|
||||
|
||||
for (auto& pos : declPlacesSymbol)
|
||||
{
|
||||
if (pos.first.first == file)
|
||||
{
|
||||
const int line = pos.first.second;
|
||||
if (range.first <= line && line <= range.second)
|
||||
return pos.second;
|
||||
} // may be in include?
|
||||
else if (allFilesInProj.find(pos.first.first) == allFilesInProj.end() && allFilesInProj.size())
|
||||
{
|
||||
auto it = declPlacesSymbolByFile.find(file);
|
||||
if (it != declPlacesSymbolByFile.end() && it->second.find(pos.first) != it->second.end())
|
||||
{
|
||||
auto s = it->second.find(pos.first);
|
||||
return s->second;
|
||||
}
|
||||
else
|
||||
#if __SPF
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#if __SPF
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Symbol* GetDeclSymbol() const { return declSymbol; }
|
||||
void SetDeclSymbol(Symbol *s) { declSymbol = s; }
|
||||
|
||||
const STRING& GetArrayUniqKey() const { return uniqKey; }
|
||||
|
||||
STRING GetIndepUniqName() const { return shortName + locationPos.second + TO_STR(dimSize); }
|
||||
|
||||
const SET<STRING>& GetRegionsName() const { return containsInRegions; }
|
||||
void SetRegionPlace(const STRING ®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;
|
||||
depracateToDistribute[dim] = value;
|
||||
}
|
||||
|
||||
void DeprecateAllDims()
|
||||
{
|
||||
for (int dim = 0; dim < dimSize; ++dim)
|
||||
depracateToDistribute[dim] = true;
|
||||
}
|
||||
|
||||
bool IsDimDepracated(const int dim) const
|
||||
{
|
||||
if (dim >= dimSize)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
if (templateDimsOrder.size() == 0)
|
||||
return depracateToDistribute[dim];
|
||||
else
|
||||
return depracateToDistribute[templateDimsOrder[dim]];
|
||||
}
|
||||
}
|
||||
|
||||
bool IsAllDeprecated() const
|
||||
{
|
||||
bool ret = true;
|
||||
for (int z = 0; z < dimSize; ++z)
|
||||
ret = ret && depracateToDistribute[z];
|
||||
return ret;
|
||||
}
|
||||
|
||||
const VECTOR<bool>& GetDeprecetedDims() const { return depracateToDistribute; }
|
||||
|
||||
int GetTypeSize() const { return typeSize; }
|
||||
|
||||
STRING AddTemplateClone(const VECTOR<dist> &newDist)
|
||||
{
|
||||
auto it = templateClones.find(newDist);
|
||||
if (it == templateClones.end())
|
||||
it = templateClones.insert(it, std::make_pair(newDist, shortName + STRING("_r") + TO_STR(templateClones.size())));
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void ClearTemplateClones()
|
||||
{
|
||||
templateClones.clear();
|
||||
templateDimsOrder.clear();
|
||||
orderedSizes.clear();
|
||||
orderedSizesExpr.clear();
|
||||
}
|
||||
|
||||
const MAP<VECTOR<dist>, STRING>& GetAllClones() const { return templateClones; }
|
||||
|
||||
void AddNewTemplateDimsOrder(const VECTOR<int> &newOrder) { templateDimsOrder = newOrder; }
|
||||
|
||||
VECTOR<int> GetNewTemplateDimsOrder() const { return templateDimsOrder; }
|
||||
|
||||
void SetDimSizesToMaxMin(bool notCopyToExpr = false)
|
||||
{
|
||||
for (int i = 0; i < dimSize; ++i)
|
||||
sizes[i] = std::make_pair((int)INT_MAX, (int)INT_MIN);
|
||||
|
||||
if (!notCopyToExpr)
|
||||
{
|
||||
for (int i = 0; i < sizesExpr.size(); ++i)
|
||||
{
|
||||
sizesExpr[i].first.second.first = sizes[i].first;
|
||||
sizesExpr[i].second.second.first = sizes[i].second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IsOmpThreadPrivate() const { return ompThreadPrivate; }
|
||||
bool IsSpfPrivate() const { return ((isNonDistribute == SPF_PRIV) || (isNonDistribute == IO_PRIV)); }
|
||||
|
||||
bool IsInEquvalence() const { return inEquivalence; }
|
||||
void SetEquvalence(bool value) { inEquivalence = value; }
|
||||
|
||||
bool IsPrivateInLoop() const { return privateInLoop; }
|
||||
void SetPrivateInLoopStatus(bool value) { privateInLoop = value; }
|
||||
|
||||
bool IsModuleSymbol() const { return locationPos.first == l_MODULE; }
|
||||
|
||||
~Array()
|
||||
{
|
||||
for (auto &templ : templateInfo)
|
||||
delete templ.second;
|
||||
}
|
||||
};
|
||||
|
||||
struct ArrayComparator
|
||||
{
|
||||
bool operator()(const Array* left, const Array* right) const
|
||||
{
|
||||
return (left->GetArrayUniqKey() > right->GetArrayUniqKey());
|
||||
}
|
||||
};
|
||||
|
||||
struct UnaryAccess
|
||||
{
|
||||
UnaryAccess()
|
||||
{
|
||||
line = -1;
|
||||
type = -1;
|
||||
underFunctionPar = -1;
|
||||
fName = "";
|
||||
count = 0;
|
||||
}
|
||||
|
||||
UnaryAccess(const PAIR<int, char>& info)
|
||||
{
|
||||
line = info.first;
|
||||
type = info.second;
|
||||
underFunctionPar = -1;
|
||||
fName = "";
|
||||
count = 1;
|
||||
}
|
||||
|
||||
UnaryAccess(const PAIR<int, char>& info, const STRING &f, const int parN)
|
||||
{
|
||||
line = info.first;
|
||||
type = info.second;
|
||||
underFunctionPar = parN;
|
||||
fName = f;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
STRING PrintInfo() const
|
||||
{
|
||||
STRING out = "#" + std::to_string(count) + " of ";
|
||||
if (type == 0)
|
||||
out += "READ ";
|
||||
else if(type == 1)
|
||||
out += "WRITE ";
|
||||
else
|
||||
out += "UNKN ";
|
||||
out += "on line " + std::to_string(line);
|
||||
if (underFunctionPar != -1)
|
||||
out += " in '#" + std::to_string(underFunctionPar + 1) + "' par of function call '" + fName + "'";
|
||||
return out;
|
||||
}
|
||||
|
||||
bool operator==(const UnaryAccess &left) const
|
||||
{
|
||||
return (line == left.line && type == left.type &&
|
||||
underFunctionPar == left.underFunctionPar && fName == left.fName);
|
||||
}
|
||||
|
||||
bool operator!=(const UnaryAccess& left) const
|
||||
{
|
||||
return !(*this == left);
|
||||
}
|
||||
|
||||
int line;
|
||||
int type; // R/W -> 0, 1
|
||||
int underFunctionPar;
|
||||
STRING fName;
|
||||
int count;
|
||||
};
|
||||
|
||||
class ArrayAccessInfo
|
||||
{
|
||||
private:
|
||||
MAP<STRING, MAP<int, VECTOR<UnaryAccess>>> accessPatterns; // file -> MAP<LINE, info>
|
||||
public:
|
||||
void AddAccessInfo(const STRING& file, const PAIR<int, char> &info, const STRING fName = "", int underParN = -1)
|
||||
{
|
||||
auto it = accessPatterns.find(file);
|
||||
if (it == accessPatterns.end())
|
||||
it = accessPatterns.insert(it, std::make_pair(file, MAP<int, VECTOR<UnaryAccess>>()));
|
||||
|
||||
bool found = false;
|
||||
UnaryAccess toAdd;
|
||||
if (underParN == -1)
|
||||
toAdd = UnaryAccess(info);
|
||||
else
|
||||
toAdd = UnaryAccess(info, fName, underParN);
|
||||
|
||||
auto itMap = it->second.find(info.first);
|
||||
if (itMap == it->second.end())
|
||||
it->second[info.first].push_back(toAdd);
|
||||
else
|
||||
{
|
||||
for (int z = 0; z < itMap->second.size(); ++z)
|
||||
{
|
||||
if (itMap->second[z] == toAdd)
|
||||
{
|
||||
found = true;
|
||||
itMap->second[z].count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == false)
|
||||
{
|
||||
if (underParN == -1)
|
||||
itMap->second.push_back(toAdd);
|
||||
else
|
||||
itMap->second.push_back(toAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkAndUpdate(const MAP<STRING, FuncInfo*>& allFuncs);
|
||||
const MAP<STRING, MAP<int, VECTOR<UnaryAccess>>>& GetAllAccessInfo() const { return accessPatterns; }
|
||||
const MAP<int, VECTOR<UnaryAccess>>* GetAccessInfoByFile(const STRING &file) const
|
||||
{
|
||||
auto it = accessPatterns.find(file);
|
||||
if (it == accessPatterns.end())
|
||||
return NULL;
|
||||
else
|
||||
return &(it->second);
|
||||
}
|
||||
};
|
||||
|
||||
void printArrayInfo(const STRING &file, const MAP<std::tuple<int, STRING, STRING>, PAIR<Array*, ArrayAccessInfo*>> &declaredArrays);
|
||||
void fixTypeOfArrayInfoWithCallGraph(MAP<std::tuple<int, STRING, STRING>, PAIR<Array*, ArrayAccessInfo*>>& declaredArrays, const MAP<STRING, FuncInfo*>& allFuncs);
|
||||
}
|
||||
#undef VECTOR
|
||||
#undef STRING
|
||||
#undef PAIR
|
||||
#undef MAP
|
||||
#undef SET
|
||||
#undef TO_STR
|
||||
766
Sapfor/_src/Distribution/ArrayAnalysis.cpp
Normal file
766
Sapfor/_src/Distribution/ArrayAnalysis.cpp
Normal file
@@ -0,0 +1,766 @@
|
||||
#include "Array.h"
|
||||
#include "../Utils/errors.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../DirectiveProcessing/directive_parser.h"
|
||||
#include "../DirectiveProcessing/directive_omp_parser.h"
|
||||
#include "../LoopAnalyzer/loop_analyzer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern int ignoreIO;
|
||||
extern map<DIST::Array*, std::tuple<int, string, string>> tableOfUniqNamesByArray;
|
||||
static set<tuple<int, string, string>> checkedArraysForWrongLocation;
|
||||
|
||||
static bool findOmpThreadPrivDecl(SgStatement* st, map<SgStatement*, set<string>>& ompThreadPrivate, SgSymbol* toFind)
|
||||
{
|
||||
|
||||
auto it = ompThreadPrivate.find(st);
|
||||
if (it == ompThreadPrivate.end())
|
||||
{
|
||||
it = ompThreadPrivate.insert(it, make_pair(st, set<string>()));
|
||||
|
||||
SgStatement* lastN = st->lastNodeOfStmt();
|
||||
set<string> dummy;
|
||||
do
|
||||
{
|
||||
st = st->lexNext();
|
||||
|
||||
auto res = parseOmpInStatement(st, dummy);
|
||||
for (auto& dir : res)
|
||||
for (auto& var : dir.threadPrivVars)
|
||||
it->second.insert(var);
|
||||
} while (st != lastN && !isSgExecutableStatement(st) && st->variant() != CONTAINS_STMT);
|
||||
}
|
||||
|
||||
if (it->second.find(toFind->identifier()) != it->second.end())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool hasAssingOpInDecl(SgSymbol* symb)
|
||||
{
|
||||
vector<SgStatement*> allDecls;
|
||||
SgStatement* decl = declaratedInStmt(symb, &allDecls);
|
||||
|
||||
for (auto& elem : allDecls)
|
||||
{
|
||||
if (elem->variant() == VAR_DECL_90)
|
||||
{
|
||||
SgExpression* list = elem->expr(0);
|
||||
while (list)
|
||||
{
|
||||
if (list->lhs()->variant() == ASSGN_OP)
|
||||
if (list->lhs()->lhs()->symbol() && OriginalSymbol(list->lhs()->lhs()->symbol()) == symb)
|
||||
return true;
|
||||
list = list->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static string getNameWithScope(SgStatement* scope, const string& currFunctionName)
|
||||
{
|
||||
if (scope && isSgProgHedrStmt(scope) && scope->symbol()->identifier() != currFunctionName)
|
||||
return scope->symbol()->identifier();
|
||||
else
|
||||
return currFunctionName;
|
||||
}
|
||||
|
||||
struct findInfo
|
||||
{
|
||||
findInfo(const string fName, SgExpression* ex, int parN, bool isWrite) :
|
||||
fName(fName), ex(ex), parN(parN), isWrite(isWrite)
|
||||
{ }
|
||||
|
||||
SgExpression* ex;
|
||||
string fName;
|
||||
int parN;
|
||||
bool isWrite;
|
||||
};
|
||||
|
||||
static void findArrayRefs (SgExpression* ex, SgStatement* st, string fName, int parN, bool isWrite,
|
||||
const map<string, vector<SgExpression*>>& commonBlocks,
|
||||
map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays,
|
||||
map<SgStatement*, set<tuple<int, string, string>>>& declaratedArraysSt,
|
||||
const set<string>& privates, const set<string>& deprecatedByIO,
|
||||
bool isExecutable, const string& currFunctionName,
|
||||
const vector<string>& inRegion,
|
||||
const set<string>& funcParNames,
|
||||
map<SgStatement*, set<string>>& ompThreadPrivate,
|
||||
const map<string, int>& distrStateFromGUI,
|
||||
const bool saveAllLocals,
|
||||
map<string, vector<Messages>>& currMessages,
|
||||
int& errorCount)
|
||||
{
|
||||
const string globalFile = current_file->filename();
|
||||
const set<string> filesInProj = getAllFilesInProject();
|
||||
|
||||
if (ex == NULL)
|
||||
return;
|
||||
stack<findInfo> queue;
|
||||
queue.push(findInfo(fName, ex, parN, isWrite));
|
||||
|
||||
while (!queue.empty())
|
||||
{
|
||||
const findInfo& curQ = queue.top();
|
||||
ex = curQ.ex;
|
||||
fName = curQ.fName;
|
||||
parN = curQ.parN;
|
||||
isWrite = curQ.isWrite;
|
||||
|
||||
queue.pop();
|
||||
|
||||
if (isArrayRef(ex))
|
||||
{
|
||||
SgSymbol* symb = OriginalSymbol(ex->symbol());
|
||||
const bool inDataStat = (symb->attributes() & DATA_BIT) != 0 || ((ex->symbol())->attributes() & DATA_BIT);
|
||||
checkNull(symb->type(), convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
const int typeSize = getSizeOfType(symb->type()->baseType());
|
||||
if (typeSize == 0)
|
||||
{
|
||||
//__spf_print(1, "Wrong type size for array %s\n", symb->identifier());
|
||||
//printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
SgStatement* decl = declaratedInStmt(symb);
|
||||
if (decl->variant() == DVM_VAR_DECL || decl->variant() == HPF_TEMPLATE_STAT)
|
||||
{
|
||||
const string tmp(decl->unparse());
|
||||
if (tmp.find("!DVM$ TEMPLATE") != string::npos)
|
||||
{
|
||||
auto sTemp = symb->identifier();
|
||||
tuple<int, string, string> uniqKey;
|
||||
bool found = false;
|
||||
for (auto& elem : declaredArrays)
|
||||
{
|
||||
if (elem.second.first->GetShortName() == sTemp)
|
||||
{
|
||||
uniqKey = elem.first;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
auto itDecl = declaratedArraysSt.find(decl);
|
||||
if (itDecl == declaratedArraysSt.end())
|
||||
itDecl = declaratedArraysSt.insert(itDecl, make_pair(decl, set<tuple<int, string, string>>()));
|
||||
itDecl->second.insert(uniqKey);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto uniqKey = getUniqName(commonBlocks, decl, symb);
|
||||
|
||||
SgStatement* scope = symb->scope();
|
||||
pair<DIST::arrayLocType, string> arrayLocation;
|
||||
|
||||
string typePrefix = "";
|
||||
while (scope && scope->variant() == STRUCT_DECL)
|
||||
{
|
||||
if (typePrefix == "")
|
||||
typePrefix = scope->symbol()->identifier();
|
||||
else
|
||||
typePrefix += scope->symbol()->identifier() + string("::");
|
||||
scope = scope->controlParent();
|
||||
}
|
||||
|
||||
if ((ex->symbol() && symb != ex->symbol()) || (scope && scope->variant() == MODULE_STMT))
|
||||
{
|
||||
if (scope)
|
||||
{
|
||||
string modName = scope->symbol()->identifier();
|
||||
arrayLocation = make_pair(DIST::l_MODULE, (typePrefix == "") ? modName : modName + "::" + typePrefix);
|
||||
}
|
||||
else //TODO: find module name with another way
|
||||
arrayLocation = make_pair(DIST::l_MODULE, "UNREC_MODULE_NAME");
|
||||
}
|
||||
else if (get<1>(uniqKey).find("common_") != string::npos)
|
||||
arrayLocation = make_pair(DIST::l_COMMON, get<1>(uniqKey).substr(strlen("common_")));
|
||||
else if (funcParNames.find(symb->identifier()) != funcParNames.end())
|
||||
arrayLocation = make_pair(DIST::l_PARAMETER, getNameWithScope(scope, currFunctionName));
|
||||
else
|
||||
{
|
||||
if (saveAllLocals || ((symb->attributes() & SAVE_BIT) != 0) || hasAssingOpInDecl(symb))
|
||||
arrayLocation = make_pair(DIST::l_LOCAL_SAVE, getNameWithScope(scope, currFunctionName));
|
||||
else
|
||||
arrayLocation = make_pair(DIST::l_LOCAL, getNameWithScope(scope, currFunctionName));
|
||||
}
|
||||
|
||||
auto itNew = declaredArrays.find(uniqKey);
|
||||
if (itNew == declaredArrays.end())
|
||||
{
|
||||
DIST::Array* arrayToAdd =
|
||||
new DIST::Array(getShortName(uniqKey), symb->identifier(), ((SgArrayType*)(symb->type()))->dimension(),
|
||||
getUniqArrayId(), decl->fileName(), decl->lineNumber(), arrayLocation, new Symbol(symb),
|
||||
findOmpThreadPrivDecl(scope, ompThreadPrivate, symb), false, false,
|
||||
inRegion, typeSize, sharedMemoryParallelization ? DIST::NO_DISTR : DIST::DISTR);
|
||||
|
||||
itNew = declaredArrays.insert(itNew, make_pair(uniqKey, make_pair(arrayToAdd, new DIST::ArrayAccessInfo())));
|
||||
|
||||
vector<pair<int, int>> sizes;
|
||||
map<DIST::Array*, set<DIST::Array*>> arrayLinksByFuncCallsNotReady;
|
||||
map<string, vector<FuncInfo*>> allFuncInfoNoReady;
|
||||
auto sizesExpr = getArraySizes(sizes, symb, decl, arrayLinksByFuncCallsNotReady, allFuncInfoNoReady);
|
||||
arrayToAdd->SetSizes(sizes);
|
||||
arrayToAdd->SetSizesExpr(sizesExpr);
|
||||
tableOfUniqNamesByArray[arrayToAdd] = uniqKey;
|
||||
}
|
||||
else // check the same location from include!
|
||||
{
|
||||
auto prevLocation = itNew->second.first->GetLocation();
|
||||
if (prevLocation != arrayLocation)
|
||||
{
|
||||
if (checkedArraysForWrongLocation.find(uniqKey) == checkedArraysForWrongLocation.end())
|
||||
{
|
||||
checkedArraysForWrongLocation.insert(uniqKey);
|
||||
__spf_print(1, "can not change declaration area of array '%s' on line %d\n", symb->identifier(), st->lineNumber());
|
||||
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Array '%s' has declaration area conflict, it might be worth applying the Include inlining pass", to_wstring(symb->identifier()).c_str());
|
||||
__spf_printToLongBuf(messageR, R184, to_wstring(symb->identifier()).c_str());
|
||||
|
||||
currMessages[st->fileName()].push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1061));
|
||||
}
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((symb->attributes() & EQUIVALENCE_BIT) != 0)
|
||||
itNew->second.first->SetEquvalence(true);
|
||||
|
||||
for (auto& reg : inRegion)
|
||||
itNew->second.first->SetRegionPlace(reg);
|
||||
|
||||
const auto oldVal = itNew->second.first->GetDistributeFlagVal();
|
||||
bool isarrayInModule = (itNew->second.first->GetLocation().first == DIST::l_MODULE);
|
||||
|
||||
if (oldVal == DIST::DISTR || oldVal == DIST::NO_DISTR)
|
||||
{
|
||||
if (itNew->second.first->IsOmpThreadPrivate())
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
else if (privates.find(symb->identifier()) != privates.end() || isarrayInModule)
|
||||
{
|
||||
//check in module
|
||||
if (itNew->second.first->GetLocation().first == DIST::l_MODULE)
|
||||
{
|
||||
for (auto& data : getAttributes<SgStatement*, SgStatement*>(decl, set<int>{ SPF_ANALYSIS_DIR }))
|
||||
{
|
||||
set<string> privatesS;
|
||||
fillPrivatesFromComment(new Statement(data), privatesS);
|
||||
if (privatesS.find(symb->identifier()) != privatesS.end())
|
||||
{
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto prev = decl->lexPrev();
|
||||
checkNull(prev, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
set<string> privatesS;
|
||||
fillPrivatesFromComment(new Statement(prev), privatesS);
|
||||
if (privatesS.find(symb->identifier()) != privatesS.end())
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
}
|
||||
else
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
}
|
||||
else if (deprecatedByIO.find(symb->identifier()) != deprecatedByIO.end())
|
||||
itNew->second.first->SetDistributeFlag(DIST::IO_PRIV);
|
||||
else if (isSgConstantSymb(symb) || inDataStat)
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
else
|
||||
{
|
||||
auto it = distrStateFromGUI.find(itNew->second.first->GetIndepUniqName());
|
||||
if (it != distrStateFromGUI.end())
|
||||
{
|
||||
if (it->second != oldVal)
|
||||
{
|
||||
itNew->second.first->SetDistributeFlag((DIST::distFlag)it->second);
|
||||
__spf_print(1, "change flag for array from cache '%s': %d -> %d\n", it->first.c_str(), oldVal, it->second);
|
||||
}
|
||||
}
|
||||
else
|
||||
itNew->second.first->SetDistributeFlag(DIST::DISTR);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeSize == 0) // unknown
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
|
||||
|
||||
if (!isExecutable)
|
||||
itNew->second.first->AddDeclInfo(make_pair(st->fileName(), st->lineNumber()), filesInProj, globalFile, new Symbol(symb));
|
||||
|
||||
if (isExecutable)
|
||||
{
|
||||
if (st->variant() != ALLOCATE_STMT && st->variant() != DEALLOCATE_STMT)
|
||||
{
|
||||
itNew->second.second->AddAccessInfo(st->fileName(), make_pair(st->lineNumber(), isWrite ? 1 : 0), fName, parN);
|
||||
itNew->second.first->AddUsagePlace(st->fileName(), st->lineNumber());
|
||||
}
|
||||
}
|
||||
|
||||
auto itDecl = declaratedArraysSt.find(decl);
|
||||
if (itDecl == declaratedArraysSt.end())
|
||||
itDecl = declaratedArraysSt.insert(itDecl, make_pair(decl, set<tuple<int, string, string>>()));
|
||||
itDecl->second.insert(uniqKey);
|
||||
|
||||
if (decl->variant() == DVM_VAR_DECL || decl->variant() == HPF_TEMPLATE_STAT)
|
||||
{
|
||||
const string tmp(decl->unparse());
|
||||
if (tmp.find("!DVM$ TEMPLATE") != string::npos)
|
||||
{
|
||||
itNew->second.first->SetTemplateFlag(true);
|
||||
//TODO: analyze align mapping
|
||||
for (int z = 0; z < itNew->second.first->GetDimSize(); ++z)
|
||||
itNew->second.first->SetMappedDim(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ex->variant() == FUNC_CALL)
|
||||
{
|
||||
SgFunctionCallExp* funcExp = (SgFunctionCallExp*)ex;
|
||||
const string fName = funcExp->funName()->identifier();
|
||||
bool intr = (isIntrinsicFunctionName(fName.c_str()) == 1);
|
||||
for (int z = 0; z < funcExp->numberOfArgs(); ++z)
|
||||
{
|
||||
//assume all arguments of function as OUT, except for inctrinsics
|
||||
bool isWriteN = intr ? false : true;
|
||||
//need to correct W/R usage with GraphCall map later
|
||||
findArrayRefs(funcExp->arg(z), st, fName, z, isWriteN, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO, isExecutable, currFunctionName, inRegion, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals, currMessages, errorCount);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isWriteN = false;
|
||||
if (ex->lhs())
|
||||
queue.push(findInfo("", ex->lhs(), -1, isWriteN));
|
||||
if (ex->rhs())
|
||||
queue.push(findInfo("", ex->rhs(), -1, isWriteN));
|
||||
//findArrayRefs(ex->lhs(), st, "", -1, isWriteN, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO, isExecutable, currFunctionName, inRegion, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals, currMessages, errorCount);
|
||||
//findArrayRefs(ex->rhs(), st, "", -1, isWriteN, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO, isExecutable, currFunctionName, inRegion, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals, currMessages, errorCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void findArrayRefInIO(SgExpression* ex, set<string>& deprecatedByIO, SgStatement* st, map<string, vector<Messages>>& currMessages)
|
||||
{
|
||||
if (ex)
|
||||
{
|
||||
if (ex->variant() == ARRAY_REF)
|
||||
{
|
||||
auto symb = ex->symbol();
|
||||
if (symb->type())
|
||||
{
|
||||
if (symb->type()->variant() == T_ARRAY)
|
||||
{
|
||||
auto found = deprecatedByIO.find(OriginalSymbol(symb)->identifier());
|
||||
if (found == deprecatedByIO.end())
|
||||
{
|
||||
deprecatedByIO.insert(found, OriginalSymbol(symb)->identifier());
|
||||
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of DVM's I/O constraints", to_wstring(symb->identifier()).c_str());
|
||||
__spf_printToLongBuf(messageR, R68, to_wstring(symb->identifier()).c_str());
|
||||
|
||||
currMessages[st->fileName()].push_back(Messages(WARR, st->lineNumber(), messageR, messageE, 1037));
|
||||
|
||||
__spf_print(1, "Array '%s' at line %d can not be distributed because of DVM's I/O constraints\n", symb->identifier(), st->lineNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
findArrayRefInIO(ex->lhs(), deprecatedByIO, st, currMessages);
|
||||
findArrayRefInIO(ex->rhs(), deprecatedByIO, st, currMessages);
|
||||
}
|
||||
}
|
||||
|
||||
static void findReshape(SgStatement* st, set<string>& privates, map<string, vector<Messages>>& currMessages)
|
||||
{
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
{
|
||||
SgExpression* exL = st->expr(0);
|
||||
SgExpression* exR = st->expr(1);
|
||||
|
||||
if (exR->variant() == FUNC_CALL && exL->variant() == ARRAY_REF)
|
||||
{
|
||||
if (exR->symbol()->identifier() == string("reshape"))
|
||||
{
|
||||
if (privates.find(exL->symbol()->identifier()) == privates.end())
|
||||
{
|
||||
privates.insert(exL->symbol()->identifier());
|
||||
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of RESHAPE", to_wstring(exL->symbol()->identifier()).c_str());
|
||||
__spf_printToLongBuf(messageR, R90, to_wstring(exL->symbol()->identifier()).c_str());
|
||||
currMessages[st->fileName()].push_back(Messages(NOTE, st->lineNumber(), messageR, messageE, 1047));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void findConstructorRef(SgStatement* st, set<string>& privates, map<string, vector<Messages>>& currMessages)
|
||||
{
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
{
|
||||
SgExpression* exL = st->expr(0);
|
||||
SgExpression* exR = st->expr(1);
|
||||
|
||||
if (exR->variant() == CONSTRUCTOR_REF && exL->variant() == ARRAY_REF)
|
||||
{
|
||||
if (privates.find(exL->symbol()->identifier()) == privates.end())
|
||||
{
|
||||
privates.insert(exL->symbol()->identifier());
|
||||
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of initializer list", to_wstring(exL->symbol()->identifier()).c_str());
|
||||
__spf_printToLongBuf(messageR, R164, to_wstring(exL->symbol()->identifier()).c_str());
|
||||
currMessages[st->fileName()].push_back(Messages(NOTE, st->lineNumber(), messageR, messageE, 1047));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void addPrivates(SgStatement* st, set<string>& privates, map<string, set<Symbol*>>& reductions,
|
||||
map<string, set<tuple<Symbol*, Symbol*, int>>>& reductionsLoc)
|
||||
{
|
||||
//after SPF preprocessing
|
||||
for (auto& data : getAttributes<SgStatement*, SgStatement*>(st, set<int>{ SPF_ANALYSIS_DIR }))
|
||||
{
|
||||
set<Symbol*> privatesS;
|
||||
fillPrivatesFromComment(new Statement(data), privatesS);
|
||||
fillReductionsFromComment(new Statement(data), reductions);
|
||||
fillReductionsFromComment(new Statement(data), reductionsLoc);
|
||||
|
||||
for (auto& elem : privatesS)
|
||||
privates.insert(elem->GetOriginal()->identifier());
|
||||
}
|
||||
|
||||
//before SPF preprocessing
|
||||
if (st->variant() == SPF_ANALYSIS_DIR)
|
||||
{
|
||||
set<Symbol*> privatesS;
|
||||
fillPrivatesFromComment(new Statement(st), privatesS);
|
||||
fillReductionsFromComment(new Statement(st), reductions);
|
||||
fillReductionsFromComment(new Statement(st), reductionsLoc);
|
||||
|
||||
for (auto& elem : privatesS)
|
||||
privates.insert(elem->GetOriginal()->identifier());
|
||||
}
|
||||
}
|
||||
|
||||
int getAllDeclaredArrays(SgFile* file, map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays,
|
||||
map<SgStatement*, set<tuple<int, string, string>>>& declaratedArraysSt, map<string, vector<Messages>>& currMessages,
|
||||
const vector<ParallelRegion*>& regions, const map<string, int>& distrStateFromGUI)
|
||||
{
|
||||
int countErrors = 0;
|
||||
|
||||
vector<SgStatement*> modules;
|
||||
findModulesInFile(file, modules);
|
||||
|
||||
map<string, set<string>> privatesByModule;
|
||||
for (auto& mod : modules)
|
||||
{
|
||||
const string modName = mod->symbol()->identifier();
|
||||
privatesByModule[modName] = set<string>();
|
||||
auto it = privatesByModule.find(modName);
|
||||
|
||||
for (SgStatement* iter = mod; iter != mod->lastNodeOfStmt(); iter = iter->lexNext())
|
||||
{
|
||||
if (iter->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
//after SPF preprocessing
|
||||
for (auto& data : getAttributes<SgStatement*, SgStatement*>(iter, set<int>{ SPF_ANALYSIS_DIR }))
|
||||
fillPrivatesFromComment(new Statement(data), it->second);
|
||||
|
||||
//before SPF preprocessing
|
||||
if (iter->variant() == SPF_ANALYSIS_DIR)
|
||||
fillPrivatesFromComment(new Statement(iter), it->second);
|
||||
}
|
||||
}
|
||||
|
||||
map<SgStatement*, set<string>> ompThreadPrivate;
|
||||
|
||||
for (int i = 0; i < file->numberOfFunctions(); ++i)
|
||||
{
|
||||
bool saveAllLocals = false;
|
||||
|
||||
SgStatement* st = file->functions(i);
|
||||
SgStatement* lastNode = st->lastNodeOfStmt();
|
||||
map<string, vector<SgExpression*>> commonBlocks;
|
||||
const string currFunctionName = st->symbol()->identifier();
|
||||
|
||||
getCommonBlocksRef(commonBlocks, st, lastNode);
|
||||
set<string> privates;
|
||||
set<string> deprecatedByIO;
|
||||
map<string, set<Symbol*>> reductions;
|
||||
map<string, set<tuple<Symbol*, Symbol*, int>>> reductionsLoc;
|
||||
set<string> funcParNames;
|
||||
|
||||
if (st->variant() != PROG_HEDR)
|
||||
{
|
||||
SgProcHedrStmt* func = (SgProcHedrStmt*)st;
|
||||
for (int z = 0; z < func->numberOfParameters(); ++z)
|
||||
funcParNames.insert(func->parameter(z)->identifier());
|
||||
|
||||
if (func->nameWithContains() != func->name().identifier()) // added contains args
|
||||
{
|
||||
SgProcHedrStmt* cp = (SgProcHedrStmt*)func->controlParent();
|
||||
checkNull(cp, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (int z = 0; z < cp->numberOfParameters(); ++z)
|
||||
funcParNames.insert(cp->parameter(z)->identifier());
|
||||
}
|
||||
}
|
||||
|
||||
for (SgStatement* iter = st; iter != lastNode; iter = iter->lexNext())
|
||||
{
|
||||
if (iter->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
addPrivates(iter, privates, reductions, reductionsLoc);
|
||||
|
||||
if (iter->variant() == USE_STMT)
|
||||
fillFromModule(iter->symbol(), privatesByModule, privates);
|
||||
|
||||
if (iter->variant() == SAVE_DECL)
|
||||
if (!iter->expr(0) && !iter->expr(1) && !iter->expr(2))
|
||||
saveAllLocals = true;
|
||||
}
|
||||
|
||||
for (SgStatement* iter = st; iter != lastNode; iter = iter->lexNext())
|
||||
{
|
||||
if (iter->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
findReshape(iter, privates, currMessages);
|
||||
findConstructorRef(iter, privates, currMessages);
|
||||
}
|
||||
|
||||
SgStatement* tmpModFind = st;
|
||||
while (tmpModFind->variant() != GLOBAL)
|
||||
{
|
||||
tmpModFind = tmpModFind->controlParent();
|
||||
if (tmpModFind->variant() == MODULE_STMT)
|
||||
fillFromModule(tmpModFind->symbol(), privatesByModule, privates);
|
||||
}
|
||||
|
||||
SgStatement* currF = st;
|
||||
SgStatement* contains = isSgProgHedrStmt(currF->controlParent());
|
||||
if (contains)
|
||||
{
|
||||
for (SgStatement* loc = contains; loc; loc = loc->lexNext())
|
||||
{
|
||||
if (isSgExecutableStatement(loc))
|
||||
break;
|
||||
if (loc->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (loc->variant() == USE_STMT)
|
||||
fillFromModule(loc->symbol(), privatesByModule, privates);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& elem : reductions)
|
||||
for (auto& setElem : elem.second)
|
||||
privates.insert(setElem->identifier());
|
||||
|
||||
for (auto& elem : reductionsLoc)
|
||||
{
|
||||
for (auto& setElem : elem.second)
|
||||
{
|
||||
privates.insert(get<0>(setElem)->identifier());
|
||||
privates.insert(get<1>(setElem)->identifier());
|
||||
}
|
||||
}
|
||||
|
||||
//analyze IO operations
|
||||
if (!ignoreIO)
|
||||
{
|
||||
for (SgStatement* iter = st; iter != lastNode; iter = iter->lexNext())
|
||||
{
|
||||
if (iter->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
SgInputOutputStmt* stIO = isSgInputOutputStmt(iter);
|
||||
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, iter->fileName(), iter->lineNumber());
|
||||
if (stIO && currRegs.size()) // deprecate to distribute arrays only in regions
|
||||
{
|
||||
int countOfItems = 0;
|
||||
for (SgExpression* items = stIO->itemList(); items; items = items->rhs(), ++countOfItems);
|
||||
|
||||
//TODO: need to add more checkers!
|
||||
if (countOfItems > 1)
|
||||
{
|
||||
for (SgExpression* items = stIO->itemList(); items; items = items->rhs())
|
||||
findArrayRefInIO(items->lhs(), deprecatedByIO, stIO, currMessages);
|
||||
}
|
||||
else if (countOfItems == 1)
|
||||
{
|
||||
auto list = stIO->specList();
|
||||
bool ok = true;
|
||||
//exclude FMT='format'
|
||||
while (list)
|
||||
{
|
||||
if (list->lhs() && list->lhs()->variant() == SPEC_PAIR)
|
||||
{
|
||||
auto ex = list->lhs();
|
||||
if (ex->lhs() && ex->rhs())
|
||||
{
|
||||
if (ex->lhs()->variant() == KEYWORD_VAL)
|
||||
{
|
||||
SgKeywordValExp* key = (SgKeywordValExp*)(ex->lhs());
|
||||
if (key->value() == string("fmt"))
|
||||
if (ex->rhs()->variant() == STRING_VAL)
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
break;
|
||||
list = list->rhs();
|
||||
}
|
||||
|
||||
//check A(i,j) for example
|
||||
auto item = stIO->itemList()->lhs();
|
||||
if (item->rhs() || item->lhs())
|
||||
ok = false;
|
||||
|
||||
if (!ok)
|
||||
findArrayRefInIO(item, deprecatedByIO, stIO, currMessages);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (st != lastNode)
|
||||
{
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (!isSPF_stat(st) && !isDVM_stat(st))
|
||||
{
|
||||
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, st->fileName(), st->lineNumber());
|
||||
vector<string> regNames;
|
||||
for (auto& reg : currRegs)
|
||||
regNames.push_back(reg->GetName());
|
||||
if (regNames.size() == 0)
|
||||
regNames.push_back("default");
|
||||
|
||||
if (st->variant() == PROC_STAT)
|
||||
{
|
||||
SgCallStmt* funcExp = (SgCallStmt*)st;
|
||||
const string fName = funcExp->symbol()->identifier();
|
||||
for (int z = 0; z < funcExp->numberOfArgs(); ++z)
|
||||
{
|
||||
findArrayRefs(funcExp->arg(z), st, fName, z, true,
|
||||
commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
|
||||
isSgExecutableStatement(st) ? true : false, currFunctionName,
|
||||
regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals,
|
||||
currMessages, countErrors);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
findArrayRefs(st->expr(i), st, "", -1, (st->variant() == ASSIGN_STAT && i == 0) ? true : false,
|
||||
commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
|
||||
isSgExecutableStatement(st) ? true : false, currFunctionName,
|
||||
regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals,
|
||||
currMessages, countErrors);
|
||||
}
|
||||
}
|
||||
st = st->lexNext();
|
||||
}
|
||||
}
|
||||
|
||||
//preprocess only module declaration
|
||||
for (auto& mod : modules)
|
||||
{
|
||||
SgStatement* st = mod->lexNext();
|
||||
SgStatement* lastNode = mod->lastNodeOfStmt();
|
||||
map<string, vector<SgExpression*>> commonBlocks;
|
||||
set<string> privates;
|
||||
set<string> deprecatedByIO;
|
||||
set<string> funcParNames;
|
||||
|
||||
fillFromModule(st->symbol(), privatesByModule, privates);
|
||||
|
||||
while (st != lastNode)
|
||||
{
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (!isSPF_stat(st) && !isDVM_stat(st))
|
||||
{
|
||||
//TODO: set clear regions for modules
|
||||
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, st->fileName(), st->lineNumber());
|
||||
vector<string> regNames;
|
||||
for (auto& reg : currRegs)
|
||||
regNames.push_back(reg->GetName());
|
||||
if (regNames.size() == 0)
|
||||
regNames.push_back("default");
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
findArrayRefs(st->expr(i), st, "", -1, false, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
|
||||
false, "NULL", regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, false,
|
||||
currMessages, countErrors);
|
||||
}
|
||||
st = st->lexNext();
|
||||
}
|
||||
}
|
||||
|
||||
//preprocess only block data declaration
|
||||
for (SgStatement* st = file->firstStatement()->lexNext(); st; st = st->lastNodeOfStmt(), st = st->lexNext())
|
||||
{
|
||||
if (st->variant() == BLOCK_DATA)
|
||||
{
|
||||
SgStatement* last = st->lastNodeOfStmt();
|
||||
SgStatement* curr = st;
|
||||
|
||||
map<string, vector<SgExpression*>> commonBlocks;
|
||||
getCommonBlocksRef(commonBlocks, st, last);
|
||||
|
||||
set<string> privates;
|
||||
set<string> deprecatedByIO;
|
||||
set<string> funcParNames;
|
||||
|
||||
string blockName = "BLOCK DATA";
|
||||
if (st->symbol())
|
||||
blockName = st->symbol()->identifier();
|
||||
|
||||
while (curr && curr != last)
|
||||
{
|
||||
//TODO: set clear regions for block data
|
||||
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, curr->fileName(), curr->lineNumber());
|
||||
vector<string> regNames;
|
||||
for (auto& reg : currRegs)
|
||||
regNames.push_back(reg->GetName());
|
||||
if (regNames.size() == 0)
|
||||
regNames.push_back("default");
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
findArrayRefs(curr->expr(i), curr, "", -1, false, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
|
||||
false, blockName, regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, false,
|
||||
currMessages, countErrors);
|
||||
curr = curr->lexNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
return countErrors;
|
||||
}
|
||||
292
Sapfor/_src/Distribution/Arrays.h
Normal file
292
Sapfor/_src/Distribution/Arrays.h
Normal file
@@ -0,0 +1,292 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include "Array.h"
|
||||
|
||||
#define MAP std::map
|
||||
#define SET std::set
|
||||
#define VECTOR std::vector
|
||||
#define STRING std::string
|
||||
#define PAIR std::pair
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
template<typename vType>
|
||||
class Arrays
|
||||
{
|
||||
private:
|
||||
unsigned nextVertexNum;
|
||||
|
||||
MAP<Array*, VECTOR<vType>> numVertsInGraph;
|
||||
MAP<STRING, Array*> arraysByName;
|
||||
SET<Array*> arrays;
|
||||
VECTOR<STRING> arrayNameByVertex;
|
||||
VECTOR<PAIR<int, Array*>> arrayDimInfoByVertex;
|
||||
public:
|
||||
Arrays() { nextVertexNum = 0; }
|
||||
|
||||
Arrays(const Arrays ©)
|
||||
{
|
||||
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
|
||||
648
Sapfor/_src/Distribution/CreateDistributionDirs.cpp
Normal file
648
Sapfor/_src/Distribution/CreateDistributionDirs.cpp
Normal file
@@ -0,0 +1,648 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <climits>
|
||||
|
||||
#include "Distribution.h"
|
||||
#include "GraphCSR.h"
|
||||
#include "Arrays.h"
|
||||
|
||||
#include "../Utils/errors.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
|
||||
using std::vector;
|
||||
using std::set;
|
||||
using std::string;
|
||||
using std::get;
|
||||
using std::make_pair;
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::tuple;
|
||||
|
||||
static set<DIST::Array*> arraysWithErrors;
|
||||
void checkDimsSizeOfArrays(const DIST::Arrays<int> &allArrays, map<string, vector<Messages>> &allMessages,
|
||||
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
|
||||
{
|
||||
const set<DIST::Array*> &arraysBase = allArrays.GetArrays();
|
||||
set<DIST::Array*> arrays;
|
||||
|
||||
for (auto &array : arraysBase)
|
||||
getRealArrayRefs(array, array, arrays, arrayLinksByFuncCalls);
|
||||
|
||||
bool ok = true;
|
||||
for (auto &array : arrays)
|
||||
{
|
||||
const vector<pair<int, int>> &sizes = array->GetSizes();
|
||||
for (int k = 0; k < sizes.size(); ++k)
|
||||
{
|
||||
if (sizes[k].first == -1 && sizes[k].second == -1)
|
||||
{
|
||||
// parallize this loops with TIE regime
|
||||
if (array->IsLoopArray())
|
||||
continue;
|
||||
|
||||
if (arraysWithErrors.find(array) == arraysWithErrors.end())
|
||||
{
|
||||
auto declPlaces = array->GetDeclInfo();
|
||||
for (auto &place : declPlaces)
|
||||
{
|
||||
string declF = place.first;
|
||||
int declL = place.second;
|
||||
|
||||
char buf[256];
|
||||
if (array->IsLoopArray())
|
||||
sprintf(buf, "More information is required about sizes of loop '%s', decl line %d, decl file %s\n", array->GetShortName().c_str(), declL, declF.c_str());
|
||||
else
|
||||
sprintf(buf, "More information is required about sizes of array '%s', decl line %d, decl file %s\n", array->GetShortName().c_str(), declL, declF.c_str());
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
arraysWithErrors.insert(array);
|
||||
|
||||
std::wstring bufE, bufR;
|
||||
__spf_printToLongBuf(bufE, L"More information is required about sizes of array '%s'", to_wstring(array->GetShortName()).c_str());
|
||||
|
||||
if (array->IsLoopArray())
|
||||
__spf_printToLongBuf(bufR, R149, to_wstring(array->GetShortName()).c_str());
|
||||
else
|
||||
__spf_printToLongBuf(bufR, R37, to_wstring(array->GetShortName()).c_str());
|
||||
|
||||
getObjectForFileFromMap(declF.c_str(), allMessages).push_back(Messages(ERROR, declL, bufR, bufE, 1012));
|
||||
}
|
||||
}
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
char buf[256];
|
||||
sprintf(buf, "Can not create distribution - unknown sizes\n");
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
throw(-1);
|
||||
}
|
||||
}
|
||||
|
||||
#define WITH_REMOVE 0
|
||||
static int templateCount = 0;
|
||||
static DIST::Array* createTemplate(DIST::Array *distArray, DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays,
|
||||
bool isMpiProgram, const map<DIST::Array*, set<DIST::Array*>>& mapOfRealRefs)
|
||||
{
|
||||
// find not connected dimentions and deprecate them
|
||||
vector<int> vInGraph;
|
||||
int err = allArrays.GetAllVertNumber(distArray, vInGraph);
|
||||
if (err != 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
#if WITH_REMOVE
|
||||
if (!distArray->IsLoopArray())
|
||||
{
|
||||
int countOfDepr = 0;
|
||||
for (int z = 0; z < vInGraph.size(); ++z)
|
||||
{
|
||||
int count = reducedG.CountOfConnectedForArray(vInGraph[z]);
|
||||
if (count <= 0)
|
||||
countOfDepr++;
|
||||
}
|
||||
|
||||
if (countOfDepr == distArray->GetDimSize())
|
||||
{
|
||||
for (int z = 0; z < distArray->GetDimSize(); ++z)
|
||||
{
|
||||
if (!distArray->IsDimMapped(z))
|
||||
distArray->DeprecateDimension(z);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int z = 0; z < vInGraph.size(); ++z)
|
||||
{
|
||||
int count = reducedG.CountOfConnectedForArray(vInGraph[z]);
|
||||
if (count <= 0)
|
||||
distArray->DeprecateDimension(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DIST::Array *templ = new DIST::Array(*distArray);
|
||||
templ->ChangeName("dvmh_temp" + std::to_string(templateCount++));
|
||||
templ->SetId(0);
|
||||
templ->SetTemplateFlag(true);
|
||||
|
||||
if (distArray->IsLoopArray())
|
||||
for (int z = 0; z < templ->GetDimSize(); ++z)
|
||||
templ->SetMappedDim(z);
|
||||
templ->SetDimSizesToMaxMin(true);
|
||||
|
||||
bool ifRemAll = false;
|
||||
#if WITH_REMOVE
|
||||
ifRemAll = templ->RemoveUnpammedDims();
|
||||
#endif
|
||||
|
||||
set<DIST::Array*> sameArrays;
|
||||
for (auto& elem : mapOfRealRefs)
|
||||
{
|
||||
for (auto& array : elem.second)
|
||||
{
|
||||
if (array == distArray)
|
||||
{
|
||||
sameArrays = elem.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sameArrays.size())
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0, templIdx = 0; i < distArray->GetDimSize(); ++i)
|
||||
{
|
||||
int vert = -1;
|
||||
const int err = allArrays.GetVertNumber(distArray, i, vert);
|
||||
if (err != 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
pair<DIST::Array*, int> result = make_pair(distArray, i);
|
||||
if (!isMpiProgram)
|
||||
{
|
||||
set<int> wasDone;
|
||||
reducedG.FindLinkWithMaxDim(vert, allArrays, result, wasDone);
|
||||
}
|
||||
|
||||
const bool isMapped = distArray->IsDimMapped(i);
|
||||
const bool isLoop = distArray->IsLoopArray();
|
||||
const bool notDeprecated = isMpiProgram ? true : !distArray->IsDimDepracated(i);
|
||||
if ((isMapped || isLoop) && notDeprecated)
|
||||
{
|
||||
AddArrayAccess(reducedG, allArrays, templ, result.first, make_pair(templIdx, result.second), 1.0, make_pair(make_pair(1, 0), make_pair(1, 0)), RR_link);
|
||||
if (result.first != distArray)
|
||||
templ->ExtendDimSize(templIdx, result.first->GetSizes()[result.second]);
|
||||
|
||||
if (isMpiProgram)
|
||||
for (auto& same: sameArrays)
|
||||
if (same != result.first)
|
||||
AddArrayAccess(reducedG, allArrays, templ, same, make_pair(templIdx, result.second), 1.0, make_pair(make_pair(1, 0), make_pair(1, 0)), RR_link);
|
||||
templIdx++;
|
||||
}
|
||||
#if !WITH_REMOVE
|
||||
else
|
||||
{
|
||||
templ->ExtendDimSize(templIdx++, make_pair(1, 1));
|
||||
__spf_print(1, "template %s was not added to graph!\n", templ->GetShortName().c_str());
|
||||
}
|
||||
#else
|
||||
else
|
||||
{
|
||||
if (ifRemAll)
|
||||
{
|
||||
AddArrayAccess(reducedG, allArrays, templ, result.first, make_pair(templIdx, result.second), 1.0, make_pair(make_pair(1, 0), make_pair(1, 0)), RR_link);
|
||||
templ->DeprecateDimension(i, false);
|
||||
if (result.first != distArray)
|
||||
templ->ExtendDimSize(templIdx, result.first->GetSizes()[result.second]);
|
||||
templIdx++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return templ;
|
||||
}
|
||||
#undef WITH_REMOVE
|
||||
|
||||
static vector<DIST::Array*> GetArrayWithMaximumDim(const vector<DIST::Array*> &arrays)
|
||||
{
|
||||
int maxDimSize = -1;
|
||||
vector<DIST::Array*> retVal;
|
||||
|
||||
for (int i = 0; i < arrays.size(); ++i)
|
||||
{
|
||||
DIST::Array *tmp = arrays[i];
|
||||
if (maxDimSize < tmp->GetDimSize())
|
||||
{
|
||||
maxDimSize = tmp->GetDimSize();
|
||||
retVal.clear();
|
||||
retVal.push_back(tmp);
|
||||
}
|
||||
else if (maxDimSize == tmp->GetDimSize())
|
||||
{
|
||||
const vector<pair<int, int>> &size1 = retVal.back()->GetSizes();
|
||||
const vector<pair<int, int>> &size2 = tmp->GetSizes();
|
||||
|
||||
if (size1 == size2)
|
||||
retVal.push_back(tmp);
|
||||
else
|
||||
{
|
||||
bool ifGT = true;
|
||||
for (int k = 0; k < size1.size(); ++k)
|
||||
if ((size1[k].second - size1[k].first) + 1 > (size2[k].second - size2[k].first) + 1)
|
||||
ifGT = false;
|
||||
|
||||
if (ifGT)
|
||||
{
|
||||
retVal.clear();
|
||||
retVal.push_back(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static void convertTrees(const map<DIST::Array*, int> &treesIn, map<int, vector<DIST::Array*>> &treesOut,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls)
|
||||
{
|
||||
for (auto it = treesIn.begin(); it != treesIn.end(); ++it)
|
||||
{
|
||||
auto foundIt = treesOut.find(it->second);
|
||||
if (foundIt == treesOut.end())
|
||||
foundIt = treesOut.insert(foundIt, make_pair(it->second, vector<DIST::Array*>()));
|
||||
|
||||
set<DIST::Array*> realRefs;
|
||||
getRealArrayRefs(it->first, it->first, realRefs, arrayLinksByFuncCalls);
|
||||
for (auto &array : realRefs)
|
||||
foundIt->second.push_back(array);
|
||||
}
|
||||
}
|
||||
|
||||
static DIST::Array* findBestInEqual(vector<DIST::Array*> &arrays, DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays)
|
||||
{
|
||||
DIST::Array *retVal = NULL;
|
||||
vector<vector<attrType>> coefsByDims;
|
||||
for (auto &array : arrays)
|
||||
{
|
||||
vector<int> verts;
|
||||
int err = allArrays.GetAllVertNumber(array, verts);
|
||||
if (err != 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
if (retVal == NULL)
|
||||
{
|
||||
retVal = array;
|
||||
for (auto &V : verts)
|
||||
coefsByDims.push_back(reducedG.GetAllAttributes(V));
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<vector<attrType>> toCmp;
|
||||
for (auto &V : verts)
|
||||
toCmp.push_back(reducedG.GetAllAttributes(V));
|
||||
for (int z = 0; z < toCmp.size(); ++z)
|
||||
{
|
||||
if (toCmp[z].size() && coefsByDims[z].size())
|
||||
{
|
||||
if (toCmp[z].back().first.first > coefsByDims[z].back().first.first)
|
||||
{
|
||||
coefsByDims = toCmp;
|
||||
retVal = array;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static bool ArraySortFunc(DIST::Array *i, DIST::Array *j) { return (i->GetName() < j->GetName()); }
|
||||
|
||||
void createDistributionDirs(DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays, DataDirective &dataDirectives, map<string, vector<Messages>> &allMessages,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, bool isMpiProgram, set<DIST::Array*> onlyThese)
|
||||
{
|
||||
checkDimsSizeOfArrays(allArrays, allMessages, arrayLinksByFuncCalls);
|
||||
|
||||
map<DIST::Array*, int> trees;
|
||||
map<int, vector<DIST::Array*>> convTrees;
|
||||
|
||||
int countTrees = reducedG.FindAllArraysTrees(trees, allArrays);
|
||||
//create one tree for all array that not found
|
||||
bool hasTemplates = false;
|
||||
map<DIST::Array*, set<DIST::Array*>> mapOfRealRefs;
|
||||
|
||||
for (auto &arrayPair : sortArraysByName(allArrays.GetArrays()))
|
||||
{
|
||||
DIST::Array* array = arrayPair.second;
|
||||
if (onlyThese.size())
|
||||
if (onlyThese.find(array) == onlyThese.end())
|
||||
continue;
|
||||
|
||||
set<DIST::Array*> realRefs;
|
||||
getRealArrayRefs(array, array, realRefs, arrayLinksByFuncCalls);
|
||||
mapOfRealRefs[array] = realRefs;
|
||||
|
||||
for (auto &realArray : realRefs)
|
||||
{
|
||||
hasTemplates = hasTemplates || realArray->IsTemplate();
|
||||
auto it = trees.find(realArray);
|
||||
if (it == trees.end())
|
||||
trees.insert(it, make_pair(realArray, ++countTrees));
|
||||
}
|
||||
}
|
||||
|
||||
vector<DIST::Array*> arraysToDist;
|
||||
if (hasTemplates == false)
|
||||
{
|
||||
convertTrees(trees, convTrees, arrayLinksByFuncCalls);
|
||||
for (auto& tree : convTrees)
|
||||
{
|
||||
sort(tree.second.begin(), tree.second.end(), ArraySortFunc);
|
||||
|
||||
vector<DIST::Array*> distrArrayV = GetArrayWithMaximumDim(tree.second);
|
||||
if (distrArrayV.size() == 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
DIST::Array *distrArray = findBestInEqual(distrArrayV, reducedG, allArrays);
|
||||
|
||||
DIST::Array *templ = createTemplate(distrArray, reducedG, allArrays, isMpiProgram, mapOfRealRefs);
|
||||
checkNull(templ, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
arraysToDist.push_back(templ);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto &array : sortArraysByName(allArrays.GetArrays()))
|
||||
{
|
||||
set<DIST::Array*> realRefs;
|
||||
getRealArrayRefs(array.second, array.second, realRefs, arrayLinksByFuncCalls);
|
||||
|
||||
for (auto &realArray : sortArraysByName(realRefs))
|
||||
if (realArray.second->IsTemplate())
|
||||
arraysToDist.push_back(realArray.second);
|
||||
}
|
||||
}
|
||||
|
||||
sort(arraysToDist.begin(), arraysToDist.end(), ArraySortFunc);
|
||||
if (arraysToDist.size())
|
||||
dataDirectives.createDirstributionVariants(arraysToDist);
|
||||
}
|
||||
|
||||
|
||||
static bool createNewAlignRule(DIST::Array *alignArray, const DIST::Arrays<int> &allArrays,
|
||||
vector<tuple<DIST::Array*, int, pair<int, int>>> &rules,
|
||||
DataDirective &dataDirectives, map<string, vector<Messages>>& SPF_messages, bool withErrors = true)
|
||||
{
|
||||
DIST::Array *alignWith = NULL;
|
||||
bool hasFreeDims = false;
|
||||
for (int i = 0; i < rules.size(); ++i)
|
||||
{
|
||||
if (alignWith == NULL && get<0>(rules[i]) != NULL)
|
||||
alignWith = get<0>(rules[i]);
|
||||
else if (alignWith != get<0>(rules[i]) && get<0>(rules[i]) != NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (get<0>(rules[i]) == NULL)
|
||||
hasFreeDims = true;
|
||||
}
|
||||
|
||||
//TODO:
|
||||
if (alignWith == NULL)
|
||||
{
|
||||
auto allDecl = alignArray->GetDeclInfo();
|
||||
for (auto& decl : allDecl)
|
||||
{
|
||||
std::wstring bufE, bufR;
|
||||
__spf_printToLongBuf(bufE, L"Can not find align rules for array '%s'", to_wstring(alignArray->GetShortName()).c_str());
|
||||
__spf_printToLongBuf(bufR, R171, to_wstring(alignArray->GetShortName()).c_str());
|
||||
if (withErrors)
|
||||
getObjectForFileFromMap(decl.first.c_str(), SPF_messages).push_back(Messages(ERROR, decl.second, bufR, bufE, 3020));
|
||||
}
|
||||
|
||||
__spf_print(1, "can not find align rules for array '%s' (full name '%s')\n", alignArray->GetShortName().c_str(), alignArray->GetName().c_str());
|
||||
}
|
||||
if (alignWith == NULL)
|
||||
return true;
|
||||
//checkNull(alignWith, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (hasFreeDims)
|
||||
{
|
||||
set<int> usedVertDims;
|
||||
vector<int> allInAlign;
|
||||
allArrays.GetAllVertNumber(alignWith, allInAlign);
|
||||
int countOfFree = 0;
|
||||
for (int i = 0; i < rules.size(); ++i)
|
||||
{
|
||||
if (get<0>(rules[i]) != NULL)
|
||||
usedVertDims.insert(get<1>(rules[i]));
|
||||
else
|
||||
countOfFree++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < allInAlign.size(); ++i)
|
||||
{
|
||||
if (usedVertDims.find(allInAlign[i]) != usedVertDims.end())
|
||||
{
|
||||
allInAlign.erase(allInAlign.begin() + i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
if (allInAlign.size() >= countOfFree)
|
||||
{
|
||||
int k = 0;
|
||||
for (int i = 0; i < rules.size(); ++i)
|
||||
{
|
||||
if (get<0>(rules[i]) == NULL || alignArray->IsDimDepracated(i))
|
||||
{
|
||||
rules[i] = make_tuple(alignWith, allInAlign[k], make_pair(0, 0));
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AlignRule newRule;
|
||||
newRule.alignArray = alignArray;
|
||||
newRule.alignWith = alignWith;
|
||||
|
||||
for (int z = 0; z < alignArray->GetDimSize(); ++z)
|
||||
{
|
||||
newRule.alignRule.push_back(make_pair(1, 0));
|
||||
|
||||
int alignToDim = -1;
|
||||
int err = allArrays.GetDimNumber(alignWith, get<1>(rules[z]), alignToDim);
|
||||
|
||||
newRule.alignRuleWith.push_back(make_pair(alignToDim, get<2>(rules[z])));
|
||||
if (get<2>(rules[z]).first == 0 && get<2>(rules[z]).second == 0)
|
||||
continue;
|
||||
|
||||
//correct template sizes
|
||||
const pair<int, int> &rule = get<2>(rules[z]);
|
||||
|
||||
if (alignWith->GetShortName().find("dvmh") != string::npos)
|
||||
{
|
||||
pair<int, int> oldSizes = alignArray->GetSizes()[z];
|
||||
if (!(oldSizes.first == oldSizes.second && oldSizes.first == -1))
|
||||
{
|
||||
oldSizes.first = oldSizes.first * rule.first + rule.second;
|
||||
oldSizes.second = oldSizes.second * rule.first + rule.second;
|
||||
alignWith->ExtendDimSize(alignToDim, oldSizes);
|
||||
}
|
||||
}
|
||||
}
|
||||
dataDirectives.alignRules.push_back(newRule);
|
||||
return false;
|
||||
}
|
||||
|
||||
static string printRule(const vector<tuple<DIST::Array*, int, pair<int, int>>> &rule)
|
||||
{
|
||||
string print = get<0>(rule[0])->GetShortName() + " : ";
|
||||
for (auto &elem : rule)
|
||||
print += "(" + std::to_string(get<2>(elem).first) + "," + std::to_string(get<2>(elem).second) + ")";
|
||||
return print;
|
||||
}
|
||||
|
||||
int createAlignDirs(DIST::GraphCSR<int, double, attrType> &reducedG, const DIST::Arrays<int> &allArrays, DataDirective &dataDirectives,
|
||||
const uint64_t regionId, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, map<string, vector<Messages>> &SPF_messages,
|
||||
set<DIST::Array*>* canNotAlign, set<DIST::Array*> onlyThese)
|
||||
{
|
||||
set<DIST::Array*> distArrays;
|
||||
const set<DIST::Array*> &arrays = allArrays.GetArrays();
|
||||
|
||||
if (dataDirectives.distrRules.size() == 0)
|
||||
{
|
||||
for (auto &array : arrays)
|
||||
if (array->IsTemplate())
|
||||
distArrays.insert(array);
|
||||
|
||||
if (distArrays.size() == 0)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < dataDirectives.distrRules.size(); ++i)
|
||||
distArrays.insert(dataDirectives.distrRules[i].first);
|
||||
}
|
||||
|
||||
bool repeat = true;
|
||||
int countRep = 0;
|
||||
while (repeat)
|
||||
{
|
||||
++countRep;
|
||||
repeat = false;
|
||||
set<pair<DIST::Array*, vector<vector<tuple<DIST::Array*, int, pair<int, int>>>>>> manyDistrRules;
|
||||
int errCount = 0;
|
||||
for (auto& arrayPair : sortArraysByName(arrays))
|
||||
{
|
||||
DIST::Array* array = arrayPair.second;
|
||||
|
||||
if (sharedMemoryParallelization != 0)
|
||||
if (onlyThese.find(array) == onlyThese.end())
|
||||
continue;
|
||||
|
||||
if (distArrays.find(array) != distArrays.end())
|
||||
continue;
|
||||
|
||||
set<DIST::Array*> realArrayRefs;
|
||||
getRealArrayRefs(array, array, realArrayRefs, arrayLinksByFuncCalls);
|
||||
|
||||
vector<vector<tuple<DIST::Array*, int, pair<int, int>>>> rules(realArrayRefs.size());
|
||||
|
||||
int i = 0;
|
||||
bool allNonDistr = true;
|
||||
bool partlyNonDistr = false;
|
||||
for (auto& arrays : sortArraysByName(realArrayRefs))
|
||||
{
|
||||
int err = reducedG.GetAlignRuleWithTemplate(arrays.second, allArrays, rules[i], regionId);
|
||||
if (err == 101)
|
||||
{
|
||||
reducedG.cleanCacheLinks();
|
||||
dataDirectives.alignRules.clear();
|
||||
repeat = true;
|
||||
break;
|
||||
}
|
||||
bool nonDistr = arrays.second->IsNotDistribute();
|
||||
allNonDistr = allNonDistr && nonDistr;
|
||||
partlyNonDistr = partlyNonDistr || nonDistr;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (repeat)
|
||||
break;
|
||||
|
||||
if (allNonDistr)
|
||||
continue;
|
||||
if (partlyNonDistr)
|
||||
{
|
||||
__spf_print(1, "detected distributed and non distributed array links by function's calls for array %s\n", array->GetName().c_str());
|
||||
auto allDecl = array->GetDeclInfo();
|
||||
for (auto& decl : allDecl)
|
||||
{
|
||||
std::wstring bufE, bufR;
|
||||
__spf_printToLongBuf(bufE, L"detected distributed and non distributed array links by function's calls for array '%s'\n", to_wstring(array->GetShortName()).c_str());
|
||||
__spf_printToLongBuf(bufR, R140, to_wstring(array->GetShortName()).c_str());
|
||||
|
||||
getObjectForFileFromMap(decl.first.c_str(), SPF_messages).push_back(Messages(ERROR, decl.second, bufR, bufE, 3020));
|
||||
}
|
||||
|
||||
for (auto& realR : realArrayRefs)
|
||||
{
|
||||
if (realR != array)
|
||||
{
|
||||
auto allDecl = realR->GetDeclInfo();
|
||||
for (auto& decl : allDecl)
|
||||
{
|
||||
std::wstring bufE, bufR;
|
||||
if (realR->IsNotDistribute())
|
||||
{
|
||||
__spf_printToLongBuf(bufE, L"detected non distributed array '%s' passed as a parameter to the procedure\n", to_wstring(realR->GetShortName()).c_str());
|
||||
__spf_printToLongBuf(bufR, R153, to_wstring(realR->GetShortName()).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
__spf_printToLongBuf(bufE, L"detected distributed array '%s' passed as a parameter to the procedure\n", to_wstring(realR->GetShortName()).c_str());
|
||||
__spf_printToLongBuf(bufR, R141, to_wstring(realR->GetShortName()).c_str());
|
||||
}
|
||||
getObjectForFileFromMap(decl.first.c_str(), SPF_messages).push_back(Messages(ERROR, decl.second, bufR, bufE, 3020));
|
||||
}
|
||||
}
|
||||
}
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
if (isAllRulesEqualWithoutArray(rules) || sharedMemoryParallelization != 0)
|
||||
{
|
||||
bool hasError = createNewAlignRule(array, allArrays, rules[0], dataDirectives, SPF_messages, canNotAlign == NULL);
|
||||
if (hasError)
|
||||
{
|
||||
if (canNotAlign)
|
||||
canNotAlign->insert(array);
|
||||
errCount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
manyDistrRules.insert(make_pair(array, rules));
|
||||
}
|
||||
|
||||
if (errCount > 0 && canNotAlign == NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (countRep > 500)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (repeat)
|
||||
continue;
|
||||
|
||||
if (manyDistrRules.size() > 0)
|
||||
{
|
||||
for (auto &array : manyDistrRules)
|
||||
{
|
||||
__spf_print(1, "different align rules for array %s was found\n", array.first->GetName().c_str());
|
||||
for (auto &rule : array.second)
|
||||
__spf_print(1, " -> %s\n", printRule(rule).c_str());
|
||||
|
||||
std::wstring bufE, bufR;
|
||||
__spf_printToLongBuf(bufE, L"different align rules for array %s were found\n", to_wstring(array.first->GetShortName()).c_str());
|
||||
__spf_printToLongBuf(bufR, R142, to_wstring(array.first->GetShortName()).c_str());
|
||||
for (auto &declPlace : array.first->GetDeclInfo())
|
||||
getObjectForFileFromMap(declPlace.first.c_str(), SPF_messages).push_back(Messages(ERROR, declPlace.second, bufR, bufE, 3020));
|
||||
}
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
13
Sapfor/_src/Distribution/CreateDistributionDirs.h
Normal file
13
Sapfor/_src/Distribution/CreateDistributionDirs.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "../Utils/errors.h"
|
||||
|
||||
void createDistributionDirs(DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays,
|
||||
DataDirective &dataDirectives, std::map<std::string, std::vector<Messages>> &allMessages,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCall, bool isMpiProgram, std::set<DIST::Array*> onlyThese = std::set<DIST::Array*>());
|
||||
int createAlignDirs(DIST::GraphCSR<int, double, attrType> &reducedG, const DIST::Arrays<int> &allArrays, DataDirective &dataDirectives,
|
||||
const uint64_t regionId, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCall, std::map<std::string,
|
||||
std::vector<Messages>> &SPF_messages, std::set<DIST::Array*>* canNotAlign = NULL, std::set<DIST::Array*> onlyThese = std::set<DIST::Array*>());
|
||||
void checkDimsSizeOfArrays(const DIST::Arrays<int>& allArrays, std::map<std::string, std::vector<Messages>>& allMessages,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
122
Sapfor/_src/Distribution/Cycle.cpp
Normal file
122
Sapfor/_src/Distribution/Cycle.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Cycle.h"
|
||||
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void Cycle<vType, wType, attrType>::
|
||||
AddArc(const pair<vType, vType> &newAcr, const wType wArc, const attrType &attrArc, const unsigned info)
|
||||
{
|
||||
Arcs.push_back(newAcr);
|
||||
wArcs.push_back(wArc);
|
||||
attrArcs.push_back(attrArc);
|
||||
compressedInfo.push_back(info);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void Cycle<vType, wType, attrType>::
|
||||
AddArc(const pair<vType, vType> &newAcr, const pair<wType, attrType> ¶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>;
|
||||
}
|
||||
|
||||
51
Sapfor/_src/Distribution/Cycle.h
Normal file
51
Sapfor/_src/Distribution/Cycle.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../Utils/types.h"
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
class Cycle
|
||||
{
|
||||
private:
|
||||
std::vector<std::pair<vType, vType>> Arcs;
|
||||
std::vector<wType> wArcs;
|
||||
std::vector<attrType> attrArcs;
|
||||
std::vector<unsigned> compressedInfo;
|
||||
|
||||
static bool comparator(std::pair<wType, vType> left, std::pair<wType, vType> right)
|
||||
{
|
||||
return left.first < right.first;
|
||||
}
|
||||
public:
|
||||
int GetNumArcs() const { return (int)Arcs.size(); }
|
||||
const std::vector<std::pair<vType, vType>>& GetArcs() const { return Arcs; }
|
||||
const std::vector<wType>& GetWeigthsArcs() const { return wArcs; }
|
||||
const std::vector<attrType>& GetAttributesArcs() const { return attrArcs; }
|
||||
|
||||
void AddArc(const std::pair<vType, vType> &newAcr, const wType wArc, const attrType &attrArc, const unsigned info);
|
||||
void AddArc(const std::pair<vType, vType> &newAcr, const std::pair<wType, attrType> ¶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;
|
||||
}
|
||||
};
|
||||
}
|
||||
629
Sapfor/_src/Distribution/Distribution.cpp
Normal file
629
Sapfor/_src/Distribution/Distribution.cpp
Normal file
@@ -0,0 +1,629 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
|
||||
#if _WIN32 && NDEBUG && __BOOST
|
||||
#include <boost/thread.hpp>
|
||||
#endif
|
||||
extern int passDone;
|
||||
|
||||
using std::pair;
|
||||
using std::set;
|
||||
using std::make_pair;
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::tuple;
|
||||
using std::vector;
|
||||
using namespace std::chrono;
|
||||
|
||||
#include "GraphCSR.h"
|
||||
#include "Arrays.h"
|
||||
#include "Array.h"
|
||||
#include "Distribution.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../Utils/errors.h"
|
||||
#include "../Utils/types.h"
|
||||
#include "../Distribution/Cycle.h"
|
||||
#include "../VisualizerCalls/get_information.h"
|
||||
#include "../VisualizerCalls/SendMessage.h"
|
||||
|
||||
extern int keepFiles;
|
||||
|
||||
#define ERROR_CHECK(err) do { if (err != 0) return err; } while(0)
|
||||
#define FIRST(x) get<0>(x)
|
||||
#define SECOND(x) get<1>(x)
|
||||
#define THIRD(x) get<2>(x)
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
//fix attributes: pair< pair<int, int>, pair<int, int> >
|
||||
template<typename attrType>
|
||||
attrType shiftByDiffInArc(const attrType& arcAttr)
|
||||
{
|
||||
pair<int, int> left = arcAttr.first;
|
||||
pair<int, int> right = arcAttr.second;
|
||||
|
||||
if (left.first == right.first)
|
||||
{
|
||||
if (left.second == right.second)
|
||||
left.second = right.second = 0;
|
||||
else if (left.second != 0 && right.second != 0)
|
||||
{
|
||||
const int diffZeroL = abs(left.second - 0);
|
||||
const int diffZeroR = abs(right.second - 0);
|
||||
if (diffZeroL < diffZeroR)
|
||||
{
|
||||
if (left.second > 0)
|
||||
{
|
||||
left.second -= diffZeroL;
|
||||
right.second -= diffZeroL;
|
||||
}
|
||||
else
|
||||
{
|
||||
left.second += diffZeroL;
|
||||
right.second += diffZeroL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (right.second > 0)
|
||||
{
|
||||
left.second -= diffZeroR;
|
||||
right.second -= diffZeroR;
|
||||
}
|
||||
else
|
||||
{
|
||||
left.second += diffZeroR;
|
||||
right.second += diffZeroR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return make_pair(left, right);
|
||||
}
|
||||
|
||||
template<typename attrType>
|
||||
attrType inverseArcByShifts(const attrType& arcAttr)
|
||||
{
|
||||
pair<int, int> left = arcAttr.first;
|
||||
pair<int, int> right = arcAttr.second;
|
||||
|
||||
if (left.first == right.first)
|
||||
{
|
||||
if (left.second < 0 && right.second < 0)
|
||||
;
|
||||
else if (left.second < 0)
|
||||
{
|
||||
std::swap(left.second, right.second);
|
||||
right.second = -right.second;
|
||||
}
|
||||
else if (right.second < 0)
|
||||
{
|
||||
std::swap(left.second, right.second);
|
||||
left.second = -left.second;
|
||||
}
|
||||
}
|
||||
return make_pair(left, right);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
int AddArrayAccess(GraphCSR<vType, wType, attrType> &G, Arrays<vType> &allArrays,
|
||||
Array *arr1, Array *arr2, pair<int, int> arc, wType arcWeight, const attrType &arcAttr,
|
||||
const uint8_t linkType)
|
||||
{
|
||||
int err = 0;
|
||||
allArrays.AddArrayToGraph(arr1);
|
||||
allArrays.AddArrayToGraph(arr2);
|
||||
|
||||
vType V1, V2;
|
||||
ERROR_CHECK(allArrays.GetVertNumber(arr1, arc.first, V1));
|
||||
ERROR_CHECK(allArrays.GetVertNumber(arr2, arc.second, V2));
|
||||
|
||||
G.AddToGraph(V1, V2, arcWeight, shiftByDiffInArc(arcAttr), linkType);
|
||||
return err;
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
static int GetIdxOfNextCycle(const vector<tuple<vType, vType, attrType>> &localDelArcs,
|
||||
const vector<Cycle<vType, wType, attrType>> &cycles,
|
||||
const vector<pair<int, int>> &indexOfConflict,
|
||||
const int idxStart = 0)
|
||||
{
|
||||
int idx = -1;
|
||||
for (int i = idxStart; i < (int)indexOfConflict.size(); ++i)
|
||||
{
|
||||
const Cycle<vType, wType, attrType> &currCycle = cycles[indexOfConflict[i].first];
|
||||
if (localDelArcs.size() == 0)
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const vector<pair<vType, vType>> &arcs = currCycle.GetArcs();
|
||||
const vector<attrType> &attributes = currCycle.GetAttributesArcs();
|
||||
bool same = false;
|
||||
|
||||
for (int k = 0; k < (int)arcs.size(); ++k)
|
||||
{
|
||||
const tuple<vType, vType, attrType> toCheck = make_tuple(arcs[k].first, arcs[k].second, attributes[k]);
|
||||
const tuple<vType, vType, attrType> toCheckRev = make_tuple(arcs[k].second, arcs[k].first, make_pair(attributes[k].second, attributes[k].first));
|
||||
|
||||
same = false;
|
||||
for (int m = 0; m < (int)localDelArcs.size(); ++m)
|
||||
{
|
||||
if (toCheck == localDelArcs[m] || toCheckRev == localDelArcs[m])
|
||||
{
|
||||
same = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (same)
|
||||
break;
|
||||
}
|
||||
if (same)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
static int GetIdxOfNextCycle(const unsigned *fastCache, const vector<unsigned> &localDelArcsShort,
|
||||
const vector<Cycle<vType, wType, attrType>> &cycles,
|
||||
const vector<pair<int, int>> &indexOfConflict,
|
||||
const int idxStart = 0)
|
||||
{
|
||||
int idx = -1;
|
||||
const pair<int, int> *data = indexOfConflict.data();
|
||||
for (int i = idxStart; i < (int)indexOfConflict.size(); ++i)
|
||||
{
|
||||
const Cycle<vType, wType, attrType> &currCycle = cycles[data[i].first];
|
||||
if (localDelArcsShort.size() == 0)
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const vector<unsigned> &shortInfo = currCycle.GetShortInfo();
|
||||
bool same = false;
|
||||
for (int k = 0; k < (int)shortInfo.size(); ++k)
|
||||
{
|
||||
if (fastCache[shortInfo[k]] == 1)
|
||||
{
|
||||
same = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (same)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
static inline bool checkGraphTrue(const int startV, const int realV, const GraphCSR<int, double, attrType> &G)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool checkGraph(const int startV, const int realV, const GraphCSR<int, double, attrType> &G)
|
||||
{
|
||||
return realV == G.CountOfConnected(startV);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType, bool check(const int startV, const int realV, const GraphCSR<vType, wType, attrType> &G)>
|
||||
static void FindBestSequenceForDelArcs(double &globalSum, vector<tuple<vType, vType, attrType>> &globalDelArcs,
|
||||
const double localSum, vector<tuple<vType, vType, attrType>> &localDelArcs,
|
||||
vector<unsigned> &localDelArcsShort,
|
||||
unsigned *fastCache,
|
||||
const vector<Cycle<vType, wType, attrType>> &cycles, const vector<pair<int, int>> &indexOfConflict,
|
||||
const int lastIndexOfConflict, const int countInTree,
|
||||
const GraphCSR<vType, wType, attrType> &graph)
|
||||
{
|
||||
int nextConflict = GetIdxOfNextCycle(fastCache, localDelArcsShort, cycles, indexOfConflict, lastIndexOfConflict + 1);
|
||||
if (nextConflict == -1)
|
||||
{
|
||||
globalSum = localSum;
|
||||
globalDelArcs = localDelArcs;
|
||||
|
||||
//char buf[256];
|
||||
//sprintf(buf, " global sum = %f, last idx of conflict %d\n", globalSum, lastIndexOfConflict);
|
||||
printf("SAPFOR: global sum = %f, last idx of conflict %d\n", globalSum, lastIndexOfConflict);
|
||||
//addToGlobalBufferAndPrint(buf);
|
||||
createNeededException();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
const Cycle<vType, wType, attrType> &conflicCycle = cycles[indexOfConflict[nextConflict].first];
|
||||
const vector<pair<vType, vType>> &arcs = conflicCycle.GetArcs();
|
||||
const vector<unsigned> &shortInfo = conflicCycle.GetShortInfo();
|
||||
const vector<wType> &weights = conflicCycle.GetWeigthsArcs();
|
||||
const vector<attrType> &attributes = conflicCycle.GetAttributesArcs();
|
||||
|
||||
for (int i = 0; i < (int)arcs.size(); ++i)
|
||||
{
|
||||
const pair<vType, vType> &currArc = arcs[i];
|
||||
const wType currW = weights[i];
|
||||
const attrType &currAttr = attributes[i];
|
||||
|
||||
if (!check(currArc.first, countInTree, graph))
|
||||
continue;
|
||||
else
|
||||
{
|
||||
if (localSum + currW < globalSum)
|
||||
{
|
||||
localDelArcs.push_back(make_tuple(currArc.first, currArc.second, currAttr));
|
||||
localDelArcsShort.push_back(shortInfo[i]);
|
||||
fastCache[shortInfo[i]] = 1;
|
||||
|
||||
FindBestSequenceForDelArcs
|
||||
<vType, wType, attrType, check>
|
||||
(globalSum, globalDelArcs, localSum + currW, localDelArcs, localDelArcsShort, fastCache, cycles, indexOfConflict, nextConflict, countInTree, graph);
|
||||
|
||||
fastCache[shortInfo[i]] = 0;
|
||||
localDelArcs.pop_back();
|
||||
localDelArcsShort.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
createNeededException();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
static void CountConflictVarints(int64_t &countVars,
|
||||
vector<unsigned> &localDelArcsShort, unsigned *fastCache,
|
||||
const vector<Cycle<vType, wType, attrType>> &cycles, const vector<pair<int, int>> &indexOfConflict,
|
||||
const int lastIndexOfConflict)
|
||||
{
|
||||
int nextConflict = GetIdxOfNextCycle(fastCache, localDelArcsShort, cycles, indexOfConflict, lastIndexOfConflict + 1);
|
||||
if (nextConflict == -1)
|
||||
{
|
||||
countVars++;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
const Cycle<vType, wType, attrType> &conflicCycle = cycles[indexOfConflict[nextConflict].first];
|
||||
const vector<unsigned> &shortInfo = conflicCycle.GetShortInfo();
|
||||
|
||||
for (int i = 0; i < (int)shortInfo.size(); ++i)
|
||||
{
|
||||
localDelArcsShort.push_back(shortInfo[i]);
|
||||
fastCache[shortInfo[i]] = 1;
|
||||
|
||||
CountConflictVarints(countVars, localDelArcsShort, fastCache, cycles, indexOfConflict, nextConflict);
|
||||
|
||||
fastCache[shortInfo[i]] = 0;
|
||||
localDelArcsShort.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define DEGUB_DEL_ALL_CYCLES 0
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
static void FindNonConflictDelArcs(vector<tuple<vType, vType, attrType>> &delArcs, const vector<Cycle<vType, wType, attrType>> &cycles)
|
||||
{
|
||||
vector<pair<int, int>> idxOfLoops(cycles.size());
|
||||
// fill indexs for all lopps for using 'GetIdxOfNextCycle' procedure
|
||||
for (int i = 0; i < (int)cycles.size(); ++i)
|
||||
#if !DEGUB_DEL_ALL_CYCLES
|
||||
idxOfLoops[i] = std::make_pair(i, 0);
|
||||
#else
|
||||
{
|
||||
const std::vector<pair<vType, vType>> &arcs = cycles[i].GetArcs();
|
||||
const std::vector<attrType> &attrs = cycles[i].GetAttributesArcs();
|
||||
for (int i = 0; i < arcs.size(); ++i)
|
||||
delArcs.push_back(std::make_tuple(arcs[i].first, arcs[i].second, attrs[i]));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !DEGUB_DEL_ALL_CYCLES
|
||||
int idxNext = -1;
|
||||
do
|
||||
{
|
||||
idxNext = GetIdxOfNextCycle(delArcs, cycles, idxOfLoops, idxNext + 1);
|
||||
if (idxNext != -1)
|
||||
{
|
||||
std::pair<vType, vType> arc = cycles[idxNext].GetArcs()[0];
|
||||
attrType attr = cycles[idxNext].GetAttributesArcs()[0];
|
||||
delArcs.push_back(std::make_tuple(arc.first, arc.second, attr));
|
||||
}
|
||||
} while (idxNext != -1);
|
||||
#endif
|
||||
}
|
||||
#undef DEGUB_DEL_ALL_CYCLES
|
||||
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
static pair<bool, double> CreateOptimalAlignementTree(GraphCSR<vType, wType, attrType> &G, const Arrays<vType> &allArrays,
|
||||
vector<tuple<vType, vType, attrType>> &toDelArcs, bool needPrint = true, bool useSavedQ = false)
|
||||
{
|
||||
double globalSum = 0;
|
||||
bool allOnlySecondType = true;
|
||||
|
||||
vector<vType> trees;
|
||||
vector<vector<vType>> vertByTrees;
|
||||
set<vType> unqieTrees = G.FindTrees(trees, vertByTrees);
|
||||
|
||||
__spf_print(needPrint, " GRAPH size: |V| = %d, |E| = %d\n", G.GetNumberOfV(), G.GetNumberOfE() / 2);
|
||||
__spf_print(needPrint, " TREES count %d\n", (int)unqieTrees.size());
|
||||
vector<unsigned char> tmp;
|
||||
for (int z = 0; z < vertByTrees.size(); ++z)
|
||||
if (vertByTrees[z].size())
|
||||
__spf_print(needPrint, " TREES %d: V = %d, E = %d\n", z, (int)vertByTrees[z].size(), G.MakeConnected(vertByTrees[z][0], tmp).second);
|
||||
else
|
||||
__spf_print(needPrint, " TREES %d: V = %d, E = %d\n", z, 0, 0);
|
||||
|
||||
toDelArcs = G.CreateMaximumSpanningTree();
|
||||
return make_pair(allOnlySecondType, globalSum);
|
||||
|
||||
// OLD ALGORITHM, THIS IS unreachable code !!
|
||||
vector<vector<Cycle<vType, wType, attrType>>> AllCycles;
|
||||
|
||||
G.GetAllSimpleLoops(AllCycles, needPrint, useSavedQ);
|
||||
toDelArcs.clear();
|
||||
|
||||
for (int k = 0; k < AllCycles.size(); ++k)
|
||||
{
|
||||
unsigned maxElem = 0;
|
||||
bool onlySecondConflictType = true;
|
||||
|
||||
for (auto &elem : AllCycles[k])
|
||||
for (auto &cycleShortInfo : elem.GetShortInfo())
|
||||
maxElem = std::max(maxElem, cycleShortInfo);
|
||||
|
||||
if (maxElem != 0 && needPrint)
|
||||
printf(" SAPFOR: max elem for cache %lld, in MB: %f\n", maxElem, maxElem / 1024. / 1024. * sizeof(unsigned));
|
||||
|
||||
unsigned *fastCache = new unsigned[maxElem];
|
||||
memset(fastCache, 0, sizeof(unsigned) * maxElem);
|
||||
|
||||
char buf[256];
|
||||
if (needPrint)
|
||||
{
|
||||
sprintf(buf, " PROF: [%d TREE]:\n", k);
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
|
||||
double globalSumLocal = (double)INT32_MAX;
|
||||
vector<pair<vType, vType>> indexOfConflict;
|
||||
vector<Cycle<vType, wType, attrType>> &cycles = AllCycles[k];
|
||||
|
||||
vector<tuple<vType, vType, attrType>> localDelArcs;
|
||||
vector<unsigned> localDelArcShort;
|
||||
|
||||
G.SortLoopsBySize(cycles, needPrint);
|
||||
G.SortLoopsByWeight(cycles, needPrint);
|
||||
|
||||
for (int i = 0; i < (int)cycles.size(); ++i)
|
||||
cycles[i].SortArcs();
|
||||
|
||||
int countConflicts = G.GetConflictCycles(cycles, allArrays, indexOfConflict, needPrint);
|
||||
|
||||
if (needPrint)
|
||||
{
|
||||
sprintf(buf, " num of conflict cycles %d\n", countConflicts);
|
||||
printf("SAPFOR: num of conflict cycles %d\n", countConflicts);
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
|
||||
if (countConflicts != 0)
|
||||
{
|
||||
int typeConflict[2] = { 0, 0 };
|
||||
for (int i = 0; i < indexOfConflict.size(); ++i)
|
||||
typeConflict[indexOfConflict[i].second]++;
|
||||
if (needPrint)
|
||||
{
|
||||
sprintf(buf, " num of type1 = %d, type2 = %d\n", typeConflict[0], typeConflict[1]);
|
||||
printf("SAPFOR: num of type1 = %d, type2 = %d\n", typeConflict[0], typeConflict[1]);
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
|
||||
if (typeConflict[0])
|
||||
{
|
||||
onlySecondConflictType = false;
|
||||
allOnlySecondType = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (needPrint)
|
||||
{
|
||||
#if _WIN32
|
||||
wstring treeM = L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> " + std::to_wstring(k + 1) + L"/" + std::to_wstring(AllCycles.size());
|
||||
#else
|
||||
wstring treeM = L"conflict resolution, processing group " + std::to_wstring(k + 1) + L"/" + std::to_wstring(AllCycles.size());
|
||||
#endif
|
||||
sendMessage_2lvl(treeM);
|
||||
|
||||
}
|
||||
|
||||
auto timeR = steady_clock::now();
|
||||
if (countConflicts != 0)
|
||||
{
|
||||
const int countInTree = G.CountOfConnected(cycles[indexOfConflict[0].first].GetArcs()[0].first);
|
||||
const int lastIndexOfConflict = -1;
|
||||
|
||||
if (needPrint)
|
||||
printf("SAPFOR: before del %d\n", countInTree);
|
||||
|
||||
/*int64_t countVars = 0;
|
||||
CountConflictVarints(countVars, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict);
|
||||
printf("SAPFOR: count of vars %lld\n", countVars);*/
|
||||
|
||||
if (onlySecondConflictType)
|
||||
FindBestSequenceForDelArcs
|
||||
<vType, wType, attrType, checkGraph>
|
||||
(globalSumLocal, toDelArcs, 0, localDelArcs, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict, countInTree, G);
|
||||
else
|
||||
FindBestSequenceForDelArcs
|
||||
<vType, wType, attrType, checkGraphTrue>
|
||||
(globalSumLocal, toDelArcs, 0, localDelArcs, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict, countInTree, G);
|
||||
|
||||
if (needPrint)
|
||||
{
|
||||
auto tmpReducedG = G;
|
||||
tmpReducedG.RemovedEdges(toDelArcs, allArrays);
|
||||
if (needPrint)
|
||||
printf("SAPFOR: after del %d\n", tmpReducedG.CountOfConnected(cycles[indexOfConflict[0].first].GetArcs()[0].first));
|
||||
}
|
||||
globalSum += globalSumLocal;
|
||||
}
|
||||
|
||||
if (needPrint)
|
||||
{
|
||||
sprintf(buf, "PROF: FindBestSequenceForDelArcs: %f sec\n", (duration_cast<duration<double>>(steady_clock::now() - timeR)).count());
|
||||
printf("SAPFOR: time of FindBestSequenceForDelArcs %f sec\n", (duration_cast<duration<double>>(steady_clock::now() - timeR)).count());
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
|
||||
timeR = steady_clock::now();
|
||||
FindNonConflictDelArcs(toDelArcs, cycles);
|
||||
if (needPrint)
|
||||
{
|
||||
sprintf(buf, "PROF: FindNonConflictDelArcs %f\n", (duration_cast<duration<double>>(steady_clock::now() - timeR)).count());
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
|
||||
delete []fastCache;
|
||||
}
|
||||
|
||||
if (needPrint)
|
||||
sendMessage_2lvl(L"");
|
||||
|
||||
return make_pair(allOnlySecondType, globalSum);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void createOptimalDistribution(GraphCSR<vType, wType, attrType> &G, GraphCSR<vType, wType, attrType> &reducedG,
|
||||
const Arrays<vType> &allArrays, const uint64_t regionNum, bool onlyGraph)
|
||||
{
|
||||
vector<tuple<int, int, attrType>> toDelArcs;
|
||||
|
||||
if (G.GetNumberOfE() == 0)
|
||||
return;
|
||||
|
||||
double globalSum = 0;
|
||||
|
||||
|
||||
string FullName = "_graph_full_reg" + std::to_string(regionNum) + ".txt";
|
||||
string ReducedName = "_graph_reduced_reg" + std::to_string(regionNum) + ".txt";
|
||||
//__spf_print(1, "flag keepFiles %d, flag onlyGraph %d\n", keepFiles, onlyGraph);
|
||||
|
||||
if (keepFiles)
|
||||
{
|
||||
if (!onlyGraph)
|
||||
G.CreateGraphWiz(FullName.c_str(), toDelArcs, allArrays, false);
|
||||
else
|
||||
G.CreateGraphWiz(FullName.c_str(), vector<tuple<int, int, attrType>>(), allArrays, true);
|
||||
}
|
||||
|
||||
if (!onlyGraph)
|
||||
{
|
||||
G.HighlightLinks();
|
||||
|
||||
//old simple algorithm
|
||||
//G.RemoveMultipleArcsByWeights();
|
||||
|
||||
//new algorithm with optimal strategy
|
||||
G.RemoveMultipleArcsOptimal();
|
||||
|
||||
pair<bool, double> retVal = CreateOptimalAlignementTree(G, allArrays, toDelArcs);
|
||||
globalSum = retVal.second;
|
||||
bool onlySecondType = retVal.first;
|
||||
|
||||
reducedG = G;
|
||||
reducedG.RemovedEdges(toDelArcs, allArrays);
|
||||
|
||||
double maxWeight = reducedG.CalculateSumOfWeights() + 1;
|
||||
//try to resolve conflicts of 1 type
|
||||
const set<Array*> &arrays = allArrays.GetArrays();
|
||||
|
||||
vector<Array*> arraysV;
|
||||
arraysV.assign(arrays.begin(), arrays.end());
|
||||
|
||||
for (int z = 0; z < arraysV.size(); ++z)
|
||||
{
|
||||
const DIST::Array *array = arraysV[z];
|
||||
|
||||
#ifdef _WIN32
|
||||
wstring treeM = L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> " + std::to_wstring(z + 1) + L"/" + std::to_wstring(arrays.size());
|
||||
#else
|
||||
wstring treeM = L"conflict resolution, processing array " + std::to_wstring(z + 1) + L"/" + std::to_wstring(arrays.size());
|
||||
#endif
|
||||
sendMessage_2lvl(treeM);
|
||||
|
||||
vector<vType> verts;
|
||||
|
||||
if (array->GetDimSize() == 1)
|
||||
continue;
|
||||
|
||||
int err = allArrays.GetAllVertNumber(array, verts);
|
||||
if (err != 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
attrType tmpPair = make_pair(make_pair(1, 0), make_pair(1, 0));
|
||||
|
||||
for (int i = 0; i < verts.size(); ++i)
|
||||
{
|
||||
for (int j = i + 1; j < verts.size(); ++j)
|
||||
{
|
||||
GraphCSR<vType, wType, attrType> findConflict(reducedG);
|
||||
findConflict.AddToGraph(verts[i], verts[j], maxWeight, tmpPair, WW_link);
|
||||
|
||||
vector<tuple<int, int, attrType>> toDelArcsLocal;
|
||||
globalSum = CreateOptimalAlignementTree(findConflict, allArrays, toDelArcsLocal, false, true).second;
|
||||
if (toDelArcsLocal.size() != 0)
|
||||
reducedG.RemovedEdges(toDelArcsLocal, allArrays);
|
||||
}
|
||||
}
|
||||
}
|
||||
sendMessage_2lvl(L"");
|
||||
}
|
||||
else
|
||||
{
|
||||
reducedG = G;
|
||||
reducedG.RemoveMultipleArcsByWeights();
|
||||
}
|
||||
|
||||
if (keepFiles)
|
||||
reducedG.CreateGraphWiz(ReducedName.c_str(), vector<tuple<int, int, attrType>>(), allArrays, true);
|
||||
}
|
||||
|
||||
template void createOptimalDistribution(GraphCSR<int, double, attrType> &G, GraphCSR<int, double, attrType> &reducedG, const Arrays<int> &allArrays, const uint64_t regionNum, bool onlyGraph);
|
||||
template int AddArrayAccess(GraphCSR<int, double, attrType> &G, Arrays<int> &allArrays, Array *arr1, Array *arr2, pair<int, int> arc, double arcWeight, const attrType &arcAttr, const uint8_t linkType);
|
||||
template attrType shiftByDiffInArc(const attrType& arcAttr);
|
||||
template attrType inverseArcByShifts(const attrType& arcAttr);
|
||||
}
|
||||
|
||||
#undef ERROR_CHECK
|
||||
#undef FIRST
|
||||
#undef SECOND
|
||||
#undef THIRD
|
||||
28
Sapfor/_src/Distribution/Distribution.h
Normal file
28
Sapfor/_src/Distribution/Distribution.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
|
||||
#include "GraphCSR.h"
|
||||
#include "Arrays.h"
|
||||
#include "Array.h"
|
||||
|
||||
namespace DIST = Distribution;
|
||||
namespace Distribution
|
||||
{
|
||||
template<typename attrType>
|
||||
attrType shiftByDiffInArc(const attrType& arcAttr);
|
||||
|
||||
template<typename attrType>
|
||||
attrType inverseArcByShifts(const attrType& arcAttr);
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
int AddArrayAccess(GraphCSR<vType, wType, attrType> &G, Arrays<vType> &allArrays,
|
||||
Array *arr1, Array *arr2, std::pair<int, int> arc, wType arcWeight,
|
||||
const attrType &arcAttr, const uint8_t linkType);
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void createOptimalDistribution(GraphCSR<vType, wType, attrType> &G, GraphCSR<vType, wType, attrType> &reducedG,
|
||||
const Arrays<vType> &allArrays, const uint64_t regionNum, bool onlyGraph);
|
||||
}
|
||||
1324
Sapfor/_src/Distribution/DvmhDirective.cpp
Normal file
1324
Sapfor/_src/Distribution/DvmhDirective.cpp
Normal file
File diff suppressed because it is too large
Load Diff
184
Sapfor/_src/Distribution/DvmhDirective.h
Normal file
184
Sapfor/_src/Distribution/DvmhDirective.h
Normal file
@@ -0,0 +1,184 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "Array.h"
|
||||
#include "DvmhDirectiveBase.h"
|
||||
#include "../Utils/AstWrapper.h"
|
||||
#include "../Utils/types.h"
|
||||
#include "../Utils/utils.h"
|
||||
|
||||
extern int sharedMemoryParallelization;
|
||||
|
||||
struct LoopGraph;
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
template<typename vType, typename wType, typename attrType> class GraphCSR;
|
||||
template<typename vType> class Arrays;
|
||||
}
|
||||
namespace DIST = Distribution;
|
||||
|
||||
struct AlignRule : public AlignRuleBase
|
||||
{
|
||||
public:
|
||||
Statement* GenRule(File *file, const int variant) const;
|
||||
};
|
||||
|
||||
struct DistrVariant : public DistrVariantBase
|
||||
{
|
||||
public:
|
||||
DistrVariant(const std::vector<dist> &distRule) : DistrVariantBase(distRule) { }
|
||||
void GenRule(File *file, Expression *arrayRef, const std::vector<int> &newOrder) const;
|
||||
std::vector<Expression*> GenRuleSt(File *file, const std::vector<int> &newOrder) const;
|
||||
};
|
||||
|
||||
struct DataDirective : Directive
|
||||
{
|
||||
public:
|
||||
std::vector<AlignRule> alignRules;
|
||||
std::vector<std::pair<DIST::Array*, std::vector<DistrVariant>>> distrRules;
|
||||
public:
|
||||
std::vector<std::pair<DIST::Array*, std::vector<DistrVariant>>> GetDistrRules() const { return distrRules; }
|
||||
void createDirstributionVariants(const std::vector<DIST::Array*> &arraysToDist);
|
||||
std::vector<std::string> GenRule(const std::vector<int> &rules) const;
|
||||
std::vector<std::string> GenAlignsRules() const;
|
||||
std::vector<AlignRule> GenAlignsRules(void*) { return alignRules; }
|
||||
std::vector<Statement*> GenRule(File *file, const std::vector<int> &rules, const int variant) const;
|
||||
std::vector<std::vector<dist>> GenRule(const std::vector<int> &rules, int) const;
|
||||
std::vector<Statement*> GenAlignsRules(File *file, const int variant) const;
|
||||
void UpdateLinks(const std::map<DIST::Array*, DIST::Array*> &oldNewArrays)
|
||||
{
|
||||
for (int i = 0; i < distrRules.size(); ++i)
|
||||
distrRules[i].first = oldNewArrays.find(distrRules[i].first)->second;
|
||||
}
|
||||
|
||||
~DataDirective()
|
||||
{
|
||||
for (auto &elem : distrRules)
|
||||
{
|
||||
if (elem.first && elem.first->IsTemplate())
|
||||
{
|
||||
delete elem.first;
|
||||
elem.first = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct CreatedDirective : Directive
|
||||
{
|
||||
std::string data;
|
||||
std::vector<Expression*> sageData;
|
||||
|
||||
explicit CreatedDirective(const std::string& data, const std::vector<Expression*>& sageData) :
|
||||
data(data), sageData(sageData)
|
||||
{ }
|
||||
|
||||
explicit CreatedDirective(const std::string& data, const std::vector<Expression*>& sageData, int line) :
|
||||
data(data), sageData(sageData)
|
||||
{
|
||||
this->line = line;
|
||||
}
|
||||
};
|
||||
|
||||
struct ParallelDirective : Directive
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> parallel;
|
||||
// tuple of <varName, A, B> on A*x + B
|
||||
std::vector<std::pair<std::string, std::pair<int, int>>> on;
|
||||
DIST::Array *arrayRef; // template
|
||||
|
||||
DIST::Array *arrayRef2;// main array in loop
|
||||
std::vector<std::pair<std::string, std::pair<int, int>>> on2;
|
||||
|
||||
std::string cloneOfTemplate; // if loop has realigns before
|
||||
|
||||
std::set<Symbol*> privates;
|
||||
// origin_Name uniqName bounds
|
||||
std::vector<std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>> shadowRenew;
|
||||
std::vector<std::vector<std::pair<int, int>>> shadowRenewShifts;
|
||||
|
||||
// origin_Name uniqName bounds
|
||||
std::vector<std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>> across;
|
||||
std::vector<std::vector<std::pair<int, int>>> acrossShifts;
|
||||
// origin_Name uniqName expression
|
||||
std::map<std::pair<std::pair<std::string, std::string>, std::string>, Expression*> remoteAccess;
|
||||
|
||||
std::map<std::string, std::set<std::string>> reduction;
|
||||
std::map<std::string, std::set<std::tuple<std::string, std::string, int>>> reductionLoc;
|
||||
public:
|
||||
ParallelDirective() : arrayRef(NULL), arrayRef2(NULL) { }
|
||||
ParallelDirective(const ParallelDirective ©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);
|
||||
811
Sapfor/_src/Distribution/DvmhDirectiveBase.cpp
Normal file
811
Sapfor/_src/Distribution/DvmhDirectiveBase.cpp
Normal file
@@ -0,0 +1,811 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "DvmhDirective.h"
|
||||
#include "../Distribution/Array.h"
|
||||
#include "../Distribution/Arrays.h"
|
||||
#include "../Distribution/GraphCSR.h"
|
||||
#include "../Utils/errors.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../GraphCall/graph_calls_func.h"
|
||||
|
||||
using std::vector;
|
||||
using std::tuple;
|
||||
using std::get;
|
||||
using std::string;
|
||||
using std::pair;
|
||||
using std::set;
|
||||
using std::map;
|
||||
|
||||
using std::set_union;
|
||||
using std::make_pair;
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
||||
template<typename setT>
|
||||
static void uniteSets(const set<setT> &first, const set<setT> &second, set<setT> &result)
|
||||
{
|
||||
vector<setT> unitedVector(first.size() + second.size());
|
||||
auto it = set_union(first.begin(), first.end(), second.begin(), second.end(), unitedVector.begin());
|
||||
unitedVector.resize(it - unitedVector.begin());
|
||||
for (int i = 0; i < (int)unitedVector.size(); ++i)
|
||||
result.insert(unitedVector[i]);
|
||||
}
|
||||
|
||||
template<typename keyT, typename valT>
|
||||
static void uniteSets(const map<keyT, valT> &first, const map<keyT, valT> &second, map<keyT, valT> &result)
|
||||
{
|
||||
vector<pair<keyT, valT>> unitedVector(first.size() + second.size());
|
||||
auto it = set_union(first.begin(), first.end(), second.begin(), second.end(), unitedVector.begin());
|
||||
unitedVector.resize(it - unitedVector.begin());
|
||||
for (int i = 0; i < (int)unitedVector.size(); ++i)
|
||||
result.insert(unitedVector[i]);
|
||||
}
|
||||
|
||||
template<typename keyT, typename valT>
|
||||
static void uniteReduction(const map<keyT, valT> &first, const map<keyT, valT> &second, map<keyT, valT> &result)
|
||||
{
|
||||
auto itF = first.begin();
|
||||
for (auto &redList : result)
|
||||
{
|
||||
auto itFound = second.find(redList.first);
|
||||
if (itFound != second.end())
|
||||
uniteSets(itF->second, itFound->second, redList.second);
|
||||
++itF;
|
||||
}
|
||||
|
||||
for (auto redList : second)
|
||||
{
|
||||
auto itFound = result.find(redList.first);
|
||||
if (itFound == result.end())
|
||||
result.insert(itFound, redList);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename vTuples>
|
||||
static vTuples uniteOnRules(const vTuples &first, const vTuples &second)
|
||||
{
|
||||
vTuples result(first.size());
|
||||
for (int i = 0; i < (int)first.size(); ++i)
|
||||
{
|
||||
bool firstStar = first[i].first == "*";
|
||||
bool secondStar = second[i].first == "*";
|
||||
if (firstStar && secondStar)
|
||||
result[i].first = "*";
|
||||
else if (firstStar)
|
||||
result[i] = second[i];
|
||||
else
|
||||
result[i] = first[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename vTuples>
|
||||
static bool hasConflictUniteOnRules(const vTuples& first, const vTuples& second)
|
||||
{
|
||||
if (first.size() != second.size())
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < (int)first.size(); ++i)
|
||||
{
|
||||
bool firstStar = first[i].first == "*";
|
||||
bool secondStar = second[i].first == "*";
|
||||
if (!firstStar && !secondStar)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ParallelDirective* operator+(const ParallelDirective &left, const ParallelDirective &right)
|
||||
{
|
||||
const ParallelDirective *first = &left;
|
||||
const ParallelDirective *second = &right;
|
||||
|
||||
ParallelDirective *result = NULL;
|
||||
checkNull(first, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
checkNull(second, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
bool condition = first->arrayRef == second->arrayRef;
|
||||
if (sharedMemoryParallelization)
|
||||
condition = !hasConflictUniteOnRules(first->on, second->on) && !hasConflictUniteOnRules(first->on2, second->on2);
|
||||
|
||||
if (condition)
|
||||
{
|
||||
if (first->on.size() != second->on.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
result = new ParallelDirective();
|
||||
|
||||
result->langType = first->langType;
|
||||
result->file = first->file;
|
||||
result->line = first->line;
|
||||
result->col = first->col;
|
||||
|
||||
result->arrayRef = first->arrayRef;
|
||||
result->arrayRef2 = first->arrayRef2;
|
||||
|
||||
result->parallel = vector<string>(first->parallel.size() + second->parallel.size());
|
||||
result->on = vector<pair<string, pair<int, int>>>(first->on.size());
|
||||
|
||||
for (int i = 0; i < (int)first->parallel.size(); ++i)
|
||||
result->parallel[i] = first->parallel[i];
|
||||
|
||||
for (int i = 0; i < (int)second->parallel.size(); ++i)
|
||||
result->parallel[i + first->parallel.size()] = second->parallel[i];
|
||||
|
||||
result->on = uniteOnRules(first->on, second->on);
|
||||
result->on2 = uniteOnRules(first->on2, second->on2);
|
||||
|
||||
uniteVectors(first->across, second->across, result->across);
|
||||
uniteVectors(first->shadowRenew, second->shadowRenew, result->shadowRenew);
|
||||
|
||||
uniteSets(first->privates, second->privates, result->privates);
|
||||
uniteSets(first->remoteAccess, second->remoteAccess, result->remoteAccess);
|
||||
|
||||
result->reduction = first->reduction;
|
||||
result->reductionLoc = first->reductionLoc;
|
||||
|
||||
uniteReduction(first->reduction, second->reduction, result->reduction);
|
||||
uniteReduction(first->reductionLoc, second->reductionLoc, result->reductionLoc);
|
||||
}
|
||||
else
|
||||
result = new ParallelDirective(left);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int findRule(const int alingDim, const vector<tuple<DIST::Array*, int, pair<int, int>>> &rule, pair<int, pair<int, int>> &retVal)
|
||||
{
|
||||
for (int i = 0; i < rule.size(); ++i)
|
||||
{
|
||||
if (get<1>(rule[i]) == alingDim)
|
||||
{
|
||||
retVal = make_pair(alingDim, get<2>(rule[i]));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline bool isNonDistributedDim(const vector<tuple<DIST::Array*, int, pair<int, int>>> &ruleForOn,
|
||||
const vector<tuple<DIST::Array*, int, pair<int, int>>> &ruleForShadow,
|
||||
const int dimN,
|
||||
const vector<pair<DIST::Array*, const DistrVariant*>> &distribution,
|
||||
const vector<pair<string, pair<int, int>>> ¶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;
|
||||
}
|
||||
|
||||
string AlignRuleBase::toString()
|
||||
{
|
||||
string retVal = "";
|
||||
|
||||
if (alignArray)
|
||||
retVal += "#" + std::to_string((long long)alignArray);
|
||||
else
|
||||
retVal += "#-1";
|
||||
|
||||
if (alignWith)
|
||||
retVal += "#" + std::to_string((long long)alignWith);
|
||||
else
|
||||
retVal += "#-1";
|
||||
|
||||
retVal += "#" + std::to_string(alignRule.size());
|
||||
for (int i = 0; i < alignRule.size(); ++i)
|
||||
retVal += "#" + std::to_string(alignRule[i].first) + "#" + std::to_string(alignRule[i].second);
|
||||
|
||||
retVal += "#" + std::to_string(alignRuleWith.size());
|
||||
for (int i = 0; i < alignRuleWith.size(); ++i)
|
||||
retVal += "#" + std::to_string(alignRuleWith[i].first)
|
||||
+ "#" + std::to_string(alignRuleWith[i].second.first)
|
||||
+ "#" + std::to_string(alignRuleWith[i].second.second);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
pair<string, string> convertDigitToPositive(const int digit)
|
||||
{
|
||||
char buf[16];
|
||||
string sign = " + ";
|
||||
if (digit < 0)
|
||||
{
|
||||
sign = " - ";
|
||||
int val = -digit;
|
||||
sprintf(buf, "%d", val);
|
||||
}
|
||||
else
|
||||
sprintf(buf, "%d", digit);
|
||||
|
||||
return make_pair(sign, buf);
|
||||
}
|
||||
|
||||
string genStringExpr(const string &letter, const pair<int, int> expr)
|
||||
{
|
||||
string retVal = "";
|
||||
if (expr.first == 0 && expr.second == 0)
|
||||
retVal = "*";
|
||||
else if (expr.second == 0)
|
||||
{
|
||||
if (expr.first == 1)
|
||||
retVal = letter;
|
||||
else
|
||||
{
|
||||
pair<string, string> digit2 = convertDigitToPositive(expr.first);
|
||||
if (digit2.first == " - ")
|
||||
digit2.second = "(-" + digit2.second + ")";
|
||||
retVal = digit2.second + string(" * ") + letter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pair<string, string> digit1 = convertDigitToPositive(expr.second);
|
||||
if (expr.first == 1)
|
||||
retVal = letter + digit1.first + digit1.second;
|
||||
else
|
||||
{
|
||||
pair<string, string> digit2 = convertDigitToPositive(expr.first);
|
||||
if (digit2.first == " - ")
|
||||
digit2.second = "(-" + digit2.second + ")";
|
||||
retVal = digit2.second + string(" * ") + letter + digit1.first + digit1.second;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
const std::vector<std::string> AlignRuleBase::alignNames = { "iEX1", "iEX2", "iEX3", "iEX4", "iEX5", "iEX6", "iEX7" };
|
||||
70
Sapfor/_src/Distribution/DvmhDirectiveBase.h
Normal file
70
Sapfor/_src/Distribution/DvmhDirectiveBase.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
typedef enum lang : int { LANG_C, LANG_F } language;
|
||||
typedef enum dist : int { BLOCK, NONE } distType;
|
||||
typedef std::pair<std::pair<int, int>, std::pair<int, int>> attrType;
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
class Array;
|
||||
}
|
||||
namespace DIST = Distribution;
|
||||
|
||||
struct Directive
|
||||
{
|
||||
lang langType;
|
||||
std::string file;
|
||||
int line;
|
||||
int col;
|
||||
|
||||
Directive ()
|
||||
{
|
||||
#if __SPF
|
||||
langType = LANG_F;
|
||||
#else
|
||||
langType = LANG_C;
|
||||
#endif
|
||||
file = "";
|
||||
line = 0;
|
||||
col = 0;
|
||||
}
|
||||
|
||||
Directive(const Directive &dir)
|
||||
{
|
||||
langType = dir.langType;
|
||||
file = dir.file;
|
||||
line = dir.line;
|
||||
col = dir.col;
|
||||
}
|
||||
};
|
||||
|
||||
struct AlignRuleBase
|
||||
{
|
||||
public:
|
||||
static const std::vector<std::string> alignNames;
|
||||
|
||||
public:
|
||||
std::string GenRuleBase() const;
|
||||
std::string toString();
|
||||
|
||||
public:
|
||||
DIST::Array *alignArray;
|
||||
DIST::Array *alignWith;
|
||||
std::vector<std::pair<int, int>> alignRule;
|
||||
std::vector<std::pair<int, std::pair<int, int>>> alignRuleWith;
|
||||
};
|
||||
|
||||
struct DistrVariantBase
|
||||
{
|
||||
public:
|
||||
std::vector<dist> distRule;
|
||||
|
||||
public:
|
||||
DistrVariantBase(const std::vector<dist> &distRule) : distRule(distRule) { }
|
||||
std::string GenRuleBase(const std::vector<int> &newOrder) const;
|
||||
};
|
||||
|
||||
bool needCorner(const DIST::Array* currArray, const std::vector<std::map<std::pair<int, int>, int>>& shiftsByAccess, const std::vector<std::vector<std::pair<int, int>>>& refsInLoop);
|
||||
12
Sapfor/_src/Distribution/DvmhDirective_func.h
Normal file
12
Sapfor/_src/Distribution/DvmhDirective_func.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include "dvm.h"
|
||||
#include "../Utils/types.h"
|
||||
|
||||
SgExpression* createAndSetNext(const int side, const int variant, SgExpression *p);
|
||||
std::vector<SgExpression*> genSubscripts(const std::vector<std::pair<int, int>> &shadowRenew, const std::vector<std::pair<int, int>> &shadowRenewShifts);
|
||||
std::pair<SgExpression*, SgExpression*> genShadowSpec(SgFile *file, const std::pair<std::string, const std::vector<std::pair<int, int>>> &shadowSpecs);
|
||||
void correctShadowSpec(SgExpression *spec, const std::vector<std::pair<int, int>> &shadowSpecs);
|
||||
2302
Sapfor/_src/Distribution/GraphCSR.cpp
Normal file
2302
Sapfor/_src/Distribution/GraphCSR.cpp
Normal file
File diff suppressed because it is too large
Load Diff
171
Sapfor/_src/Distribution/GraphCSR.h
Normal file
171
Sapfor/_src/Distribution/GraphCSR.h
Normal file
@@ -0,0 +1,171 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
|
||||
#include "../Utils/RationalNum.h"
|
||||
|
||||
typedef enum links { RR_link, WR_link, WW_link } LinkType;
|
||||
|
||||
#define MAX_LOOP_DIM 8
|
||||
#define MAX_CHAIN_LEN 8
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
class Array;
|
||||
template<typename vType> class Arrays;
|
||||
template<typename vType, typename wType, typename attrType> class Cycle;
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
class GraphCSR
|
||||
{
|
||||
private:
|
||||
vType numVerts;
|
||||
vType numEdges;
|
||||
vType lastNumOfV;
|
||||
|
||||
std::vector<vType> neighbors;
|
||||
std::vector<vType> edges;
|
||||
std::vector<wType> weights;
|
||||
std::vector<uint8_t> linkType;
|
||||
std::vector<attrType> attributes;
|
||||
std::vector<vType> localIdx;
|
||||
std::vector<vType> globalIdx;
|
||||
|
||||
//for finding
|
||||
std::vector<vType> color;
|
||||
vType *activeV;
|
||||
vType *activeE;
|
||||
std::pair<wType, attrType> *activeArcs;
|
||||
uint64_t usedMem;
|
||||
std::vector<std::pair<int, int>> treesQuality;
|
||||
|
||||
int activeCounter;
|
||||
vType findFrom;
|
||||
bool hardLinksWasUp;
|
||||
|
||||
int maxChainLen;
|
||||
int maxLoopDim;
|
||||
uint64_t maxAvailMemory;
|
||||
|
||||
std::map<vType, std::map<vType, std::tuple<int, Array*, std::pair<RationalNum, RationalNum>>>> cacheLinks;
|
||||
int countRequestsToAdd, countMissToAdd;
|
||||
private:
|
||||
GraphCSR(const std::vector<vType> &neighbors, const std::vector<vType> &edges,
|
||||
const std::vector<wType> &weights, const std::vector<vType> &localIdx,
|
||||
const std::vector<vType> &globalIdx, const std::vector<attrType> &attributes,
|
||||
const std::vector<uint8_t> &linkType, const bool hardLinksWasUp) :
|
||||
neighbors(neighbors), edges(edges), weights(weights), localIdx(localIdx),
|
||||
globalIdx(globalIdx), attributes(attributes), linkType(linkType), hardLinksWasUp(hardLinksWasUp)
|
||||
{
|
||||
numVerts = (int)neighbors.size() - 1;
|
||||
numEdges = (int)edges.size();
|
||||
}
|
||||
|
||||
vType GetLocalVNum(const vType &V, bool &ifNew);
|
||||
void AddEdgeToGraph(const vType &V1, const vType &V2, const wType &W, const attrType &attr, const bool &ifNew, const uint8_t linkType);
|
||||
void IncreaseWeight(const int &idx, const int &idxRev, const wType &W);
|
||||
int CheckExist(const vType &V1, const vType &V2, const attrType &attr, const bool &ifNew, const uint8_t &linkType);
|
||||
|
||||
//old algorithm without sort in the fly
|
||||
//TODO: need to update
|
||||
void FindLoop(std::vector<Cycle<vType, wType, attrType>> &cycles, const vType V, const vType VPrev);
|
||||
void FindLoop(std::vector<std::map<std::vector<unsigned>, Cycle<vType, wType, attrType>>> &cycles, const vType V, const vType VPrev, const std::vector<vType> &numbers);
|
||||
void RemoveDuplicates(std::vector<Cycle<vType, wType, attrType>> &cycles);
|
||||
bool findLink(const vType v1, std::pair<int, int> &inGraphAttr1, const vType v2, std::pair<int, int> &inGraphAttr2);
|
||||
std::pair<RationalNum, RationalNum> findLinkWithTempate2(const vType v1, int &templV, Array *&templ, const Arrays<vType> &allArrays, std::set<vType> wasDone);
|
||||
int findDimNumLink(const vType v, const Array *to, const Arrays<vType> &allArrays, std::set<vType> &wasDone) const;
|
||||
bool checkFirstCoefOfNode(vType node);
|
||||
bool getOptimalBoundsForNode(vType nodeFrom, vType nodeTo, int &needBound, std::pair<int, int> &bounds);
|
||||
bool hasLinkWithTempate(const vType root, const Arrays<vType> &allArrays, bool, int newValue = 0);
|
||||
public:
|
||||
GraphCSR()
|
||||
{
|
||||
ClearGraphCSR();
|
||||
}
|
||||
|
||||
GraphCSR(const GraphCSR &G) : GraphCSR(G.neighbors, G.edges, G.weights, G.localIdx, G.globalIdx, G.attributes, G.linkType, G.hardLinksWasUp)
|
||||
{
|
||||
this->lastNumOfV = G.lastNumOfV;
|
||||
this->maxLoopDim = G.maxLoopDim;
|
||||
this->maxChainLen = G.maxChainLen;
|
||||
this->maxAvailMemory = G.maxAvailMemory;
|
||||
this->countRequestsToAdd = G.countRequestsToAdd;
|
||||
this->countMissToAdd = G.countMissToAdd;
|
||||
this->treesQuality = G.treesQuality;
|
||||
}
|
||||
|
||||
void cleanCacheLinks() { cacheLinks.clear(); }
|
||||
|
||||
void ClearGraphCSR()
|
||||
{
|
||||
lastNumOfV = numVerts = numEdges = 0;
|
||||
hardLinksWasUp = false;
|
||||
neighbors.resize(0);
|
||||
edges.resize(0);
|
||||
weights.resize(0);
|
||||
linkType.resize(0);
|
||||
localIdx.resize(0);
|
||||
globalIdx.resize(0);
|
||||
attributes.resize(0);
|
||||
treesQuality.resize(0);
|
||||
|
||||
maxLoopDim = MAX_LOOP_DIM;
|
||||
maxChainLen = MAX_CHAIN_LEN;
|
||||
maxAvailMemory = 0;
|
||||
countRequestsToAdd = 0;
|
||||
countMissToAdd = 0;
|
||||
}
|
||||
|
||||
std::set<vType> FindTrees(std::vector<vType> &inTree, std::vector<std::vector<vType>> &vertByTrees);
|
||||
bool SaveGraphToFile(FILE *file);
|
||||
bool LoadGraphFromFile(FILE *file);
|
||||
int AddToGraph(const vType &V1, const vType &V2, const wType &W, const attrType &attr, const uint8_t linkType);
|
||||
void GetAllSimpleLoops(std::vector<std::vector<Cycle<vType, wType, attrType>>> &cycles, bool needPrint, bool useSavedQ);
|
||||
int SortLoopsBySize(std::vector<Cycle<vType, wType, attrType>> &cycles, bool needPrint);
|
||||
int SortLoopsByWeight(std::vector<Cycle<vType, wType, attrType>> &cycles, bool needPrint);
|
||||
int GetConflictCycles(const std::vector<Cycle<vType, wType, attrType>> &cycles, const Arrays<vType> &allArrays, std::vector<std::pair<int, int>> &indexOfConflict, bool needPrint);
|
||||
void RemoveMultipleArcsByWeights();
|
||||
void RemoveMultipleArcsOptimal();
|
||||
void RemoveVerticesByWeight();
|
||||
int CreateGraphWiz(const char *fileName, const std::vector<std::tuple<vType, vType, attrType>> &toDelArcs, const Arrays<vType> &allArrays, const bool onlyTree);
|
||||
void RemovedEdges(const std::vector<std::tuple<vType, vType, attrType>> &toDelArcs, const Arrays<vType> &allArrays);
|
||||
void HighlightLinks();
|
||||
|
||||
int GetAlignRuleForArray(Array *inputArray, const Arrays<vType> &allArrays, std::vector<std::vector<std::tuple<Array*, vType, attrType>>> &assignedArrays);
|
||||
int GetAlignRuleWithTemplate(Array *inputArray, const Arrays<vType> &allArrays, std::vector<std::tuple<Array*, vType, std::pair<int, int>>> &rules, const uint64_t regionId);
|
||||
void FindLinksBetweenArrays(const Arrays<vType> &allArrays, const Array *from, const Array *to, std::vector<int> &links) const;
|
||||
void FindLinkWithMaxDim(const vType from, const Arrays<vType> &allArrays, std::pair<Array*, int> &result, std::set<int> &wasDone);
|
||||
int FindAllArraysTrees(std::map<Array*, int> &trees, const Arrays<vType> &allArrays);
|
||||
|
||||
vType GetNumberOfV() const { return numVerts; }
|
||||
vType GetNumberOfE() const { return numEdges; }
|
||||
|
||||
void SetMaxLoopDim(const int newMaxLoopDim) { maxLoopDim = newMaxLoopDim; }
|
||||
void SetMaxChainLen(const int newMaxChainLen) { maxChainLen = newMaxChainLen; }
|
||||
int GetMaxLoopDim() const { return maxLoopDim; }
|
||||
int GetMaxChainLen() const { return maxChainLen; }
|
||||
void SetMaxAvailMemory(const uint64_t memSize) { maxAvailMemory = memSize; }
|
||||
void ChangeQuality(const int newMaxLoopDim, const int newMaxChainLen) { SetMaxLoopDim(newMaxLoopDim); SetMaxChainLen(newMaxChainLen); }
|
||||
int getCountOfReq() const { return countRequestsToAdd; }
|
||||
int getCountOfMiss() const { return countMissToAdd; }
|
||||
|
||||
std::vector<attrType> GetAllAttributes(const int vert) const;
|
||||
int CountOfConnected(const vType startV) const;
|
||||
int CountOfConnectedForArray(const vType startV) const;
|
||||
std::vector<std::tuple<vType, vType, attrType>> CreateMaximumSpanningTree();
|
||||
std::pair<int, int> MakeConnected(const vType startV, std::vector<unsigned char> &inSet) const;
|
||||
double CalculateSumOfWeights() const
|
||||
{
|
||||
double ret = 0;
|
||||
for (int z = 0; z < weights.size(); ++z)
|
||||
ret += weights[z] / 2.0;
|
||||
return ret;
|
||||
}
|
||||
void RemoveAllEdgesFromGraph(const std::map<Array*, std::vector<std::pair<int, int>>>& toDel, const Arrays<vType>& allArrays);
|
||||
};
|
||||
|
||||
std::pair<int, int> Fx(const std::pair<int, int> &x, const std::pair<int, int> &F);
|
||||
}
|
||||
38
Sapfor/_src/DvmhRegions/DvmhRegion.cpp
Normal file
38
Sapfor/_src/DvmhRegions/DvmhRegion.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "leak_detector.h"
|
||||
#include "DvmhRegion.h"
|
||||
|
||||
DvmhRegion::DvmhRegion(LoopGraph *loopNode, const std::string &fun_name) : fun_name(fun_name)
|
||||
{
|
||||
loops.push_back(loopNode);
|
||||
}
|
||||
|
||||
SgStatement* DvmhRegion::getFirstSt() const
|
||||
{
|
||||
if (loops.size() < 1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
return loops.front()->loop->GetOriginal();
|
||||
}
|
||||
|
||||
SgStatement* DvmhRegion::getLastSt() const
|
||||
{
|
||||
if (loops.size() < 1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
return loops.back()->loop->GetOriginal()->lastNodeOfStmt();
|
||||
}
|
||||
|
||||
void DvmhRegion::append(DvmhRegion& region)
|
||||
{
|
||||
for (auto& loop : region.getLoops())
|
||||
addLoop(loop);
|
||||
}
|
||||
|
||||
int DvmhRegion::getLineForSort() const
|
||||
{
|
||||
if (loops.size() == 0)
|
||||
return -1;
|
||||
|
||||
int line = loops[0]->lineNum;
|
||||
if (line < 0)
|
||||
line = loops[0]->altLineNum;
|
||||
return line;
|
||||
}
|
||||
28
Sapfor/_src/DvmhRegions/DvmhRegion.h
Normal file
28
Sapfor/_src/DvmhRegions/DvmhRegion.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GraphLoop/graph_loops_func.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class DvmhRegion
|
||||
{
|
||||
private:
|
||||
std::vector<LoopGraph*> loops;
|
||||
std::string fun_name;
|
||||
|
||||
public:
|
||||
DvmhRegion() { }
|
||||
DvmhRegion(LoopGraph *loopNode, const std::string &fun_name);
|
||||
|
||||
SgStatement* getFirstSt() const;
|
||||
SgStatement* getLastSt() const;
|
||||
|
||||
void addLoop(LoopGraph* newLoop) { loops.push_back(newLoop); }
|
||||
const std::string& getFunName() const { return fun_name; }
|
||||
void setFunName(const std::string& newName) { fun_name = newName; }
|
||||
const std::vector<LoopGraph*>& getLoops() const { return loops; }
|
||||
std::string getFileName() const { return getFirstSt()->fileName(); }
|
||||
void append(DvmhRegion& region);
|
||||
int getLineForSort() const;
|
||||
};
|
||||
|
||||
1598
Sapfor/_src/DvmhRegions/DvmhRegionInserter.cpp
Normal file
1598
Sapfor/_src/DvmhRegions/DvmhRegionInserter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
120
Sapfor/_src/DvmhRegions/DvmhRegionInserter.h
Normal file
120
Sapfor/_src/DvmhRegions/DvmhRegionInserter.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GraphCall/graph_calls_func.h"
|
||||
#include "../GraphLoop/graph_loops_func.h"
|
||||
#include "../ExpressionTransform/expr_transform.h"
|
||||
#include "../ParallelizationRegions/ParRegions.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "ReadWriteAnalyzer.h"
|
||||
#include "DvmhRegion.h"
|
||||
|
||||
|
||||
typedef std::set<DIST::Array* > ArraySet;
|
||||
struct ReadWrite
|
||||
{
|
||||
ArraySet read;
|
||||
ArraySet write;
|
||||
};
|
||||
typedef std::map<int, ReadWrite> UsageByLine;
|
||||
typedef std::map<std::string, UsageByLine> UsageByFile;
|
||||
|
||||
|
||||
class DvmhRegionInserter
|
||||
{
|
||||
// input data
|
||||
SgFile *file;
|
||||
std::map<int, LoopGraph*> loopGraphMap;
|
||||
const std::vector<LoopGraph*> loopGraph;
|
||||
const std::map<std::string, FuncInfo*> allFunctions;
|
||||
const std::vector<FuncInfo*> funcsForFile;
|
||||
bool isMpiProgram;
|
||||
|
||||
ReadWriteAnalyzer& rw_analyzer;
|
||||
std::map<FuncInfo*, std::set<LoopGraph*>> parallel_functions;
|
||||
std::set<DIST::Array*> writesToArraysInParallelLoops;
|
||||
std::set<DIST::Array*> usedArraysInParallelLoops;
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls;
|
||||
// operating data
|
||||
std::vector<DvmhRegion*> regions;
|
||||
|
||||
// region directives
|
||||
void findEdgesForRegions(const std::vector<LoopGraph*>&);
|
||||
bool hasLimitsToDvmhParallel(const LoopGraph*) const;
|
||||
void insertRegionDirectives();
|
||||
|
||||
// actual directives
|
||||
ArraySet symbs_to_arrs(std::set<SgSymbol*>) const;
|
||||
ArraySet get_used_arrs(SgStatement* st, int usage_type) const;
|
||||
ArraySet get_used_arrs_for_block(SgStatement* st, int usage_type) const;
|
||||
SgStatement* processSt(SgStatement *st, const std::vector<ParallelRegion*>* regs);
|
||||
|
||||
void insertActualDirective(SgStatement*, const ArraySet&, int, bool, const std::set<std::string>* = NULL);
|
||||
|
||||
void parFuncsInNode(LoopGraph *loop, bool isParallel);
|
||||
bool isLoopParallel(const LoopGraph *loop) const;
|
||||
std::vector<SgExpression*> getArrayList(Statement* start, Statement* end, bool left = false) const;
|
||||
ArraySet applyUseFilter(const ArraySet& block, const std::set<DIST::Array*>& filter) const;
|
||||
ArraySet excludePrivates(const ArraySet& block) const;
|
||||
ArraySet excludeRemotes(const ArraySet& block, SgStatement* remoteDir) const;
|
||||
void insertForProcCall(SgStatement* st, bool& skipGetActualIfProcCall, bool& skipActualIfProcCall);
|
||||
public:
|
||||
explicit DvmhRegionInserter(
|
||||
SgFile* curFile,
|
||||
const std::vector<LoopGraph*>& curLoopGraph,
|
||||
ReadWriteAnalyzer& rws,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const std::map<std::string, FuncInfo*>& allFunctions,
|
||||
const std::vector<FuncInfo*>& funcsForFile,
|
||||
bool mpi_program
|
||||
) : file(curFile), loopGraph(curLoopGraph), rw_analyzer(rws), arrayLinksByFuncCalls(arrayLinksByFuncCalls), allFunctions(allFunctions), funcsForFile(funcsForFile), isMpiProgram(mpi_program)
|
||||
{
|
||||
if (loopGraph.size())
|
||||
createMapLoopGraph(loopGraph, loopGraphMap);
|
||||
}
|
||||
|
||||
void insertDirectives(const std::vector<ParallelRegion*>* regs = NULL);
|
||||
void insertActualDirectives(const std::vector<ParallelRegion*>* regs);
|
||||
|
||||
void updateParallelFunctions(const std::map<std::string, std::vector<LoopGraph*>>& loopGraphs);
|
||||
void createInterfaceBlockForParallelFunctions(bool onlyRoutine = true);
|
||||
void removePrivatesFromParallelLoops();
|
||||
void addPrivatesToParallelLoops();
|
||||
void addUsedArrays(std::set<DIST::Array*>& arrays);
|
||||
void addUsedWriteArrays(std::set<DIST::Array*>& arrays);
|
||||
|
||||
void updateUsedArrays(const std::set<DIST::Array*>& used, const std::set<DIST::Array*>& usedForWrite)
|
||||
{
|
||||
ArraySet newSet = usedForWrite;
|
||||
for (auto& elem : usedForWrite)
|
||||
getRealArrayRefs(elem, elem, newSet, arrayLinksByFuncCalls);
|
||||
writesToArraysInParallelLoops = newSet;
|
||||
|
||||
newSet = used;
|
||||
for (auto& elem : used)
|
||||
getRealArrayRefs(elem, elem, newSet, arrayLinksByFuncCalls);
|
||||
usedArraysInParallelLoops = newSet;
|
||||
}
|
||||
|
||||
const std::set<FuncInfo*> getParallelFunctions() const {
|
||||
std::set<FuncInfo*> retVal;
|
||||
for (auto& elem : parallel_functions)
|
||||
retVal.insert(elem.first);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static void createInterfaceBlockForOutCall(FuncInfo* func, FuncInfo* callFrom);
|
||||
static void createInterfaceBlockForOutCalls(FuncInfo* func);
|
||||
|
||||
~DvmhRegionInserter()
|
||||
{
|
||||
for (auto& reg : regions)
|
||||
delete reg;
|
||||
}
|
||||
};
|
||||
|
||||
int insertDvmhRegions(SgProject& project, int files, const std::vector<ParallelRegion*>& parallelRegions,
|
||||
std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo,
|
||||
std::map<std::string, std::vector<LoopGraph*>> loopGraph,
|
||||
ReadWriteAnalyzer& rw_analyzer,
|
||||
std::map<std::string, std::vector<Messages>>& SPF_messages,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> arrayLinksByFuncCalls);
|
||||
72
Sapfor/_src/DvmhRegions/LoopChecker.cpp
Normal file
72
Sapfor/_src/DvmhRegions/LoopChecker.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "leak_detector.h"
|
||||
#include "LoopChecker.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void LoopChecker::updateLoopGraph(const map<string, FuncInfo*> &allFuncs)
|
||||
{
|
||||
for (auto &loopNode : loopGraph)
|
||||
updateLoopNode(loopNode, allFuncs);
|
||||
}
|
||||
|
||||
LoopCheckResults LoopChecker::updateLoopNode(LoopGraph *loop, const map<string, FuncInfo*> &allFuncs)
|
||||
{
|
||||
LoopCheckResults loopChecks = checkLoopForPurenessAndIO(loop, allFuncs);
|
||||
bool hasImpureCalls = loopChecks.hasImpureCalls;
|
||||
bool usesIO = loopChecks.usesIO;
|
||||
|
||||
if (loopChecks.linesOfIO.size() && usesIO)
|
||||
for (auto& elem : loopChecks.linesOfIO)
|
||||
loop->linesOfIO.insert(elem);
|
||||
|
||||
for (auto &nestedLoop : loop->children)
|
||||
{
|
||||
loopChecks = updateLoopNode(nestedLoop, allFuncs);
|
||||
hasImpureCalls |= loopChecks.hasImpureCalls;
|
||||
usesIO |= loopChecks.usesIO;
|
||||
}
|
||||
|
||||
loop->hasNonPureProcedures |= hasImpureCalls;
|
||||
loop->hasPrints |= usesIO;
|
||||
|
||||
return LoopCheckResults(loop->hasPrints, loop->hasNonPureProcedures);
|
||||
}
|
||||
|
||||
|
||||
// checks loop node itself, doesn't check its children
|
||||
LoopCheckResults LoopChecker::checkLoopForPurenessAndIO(const LoopGraph *loopNode, const map<string, FuncInfo*> &allFuncs) const
|
||||
{
|
||||
LoopCheckResults loopCheckResults;
|
||||
|
||||
for (auto &nameAndLineOfFuncCalled : loopNode->calls)
|
||||
{
|
||||
FuncInfo *calledFuncInfo = NULL;
|
||||
|
||||
auto it = allFuncs.find(nameAndLineOfFuncCalled.first);
|
||||
if (it != allFuncs.end())
|
||||
calledFuncInfo = it->second;
|
||||
|
||||
if (!calledFuncInfo)
|
||||
{
|
||||
if (isIntrinsicFunctionName(nameAndLineOfFuncCalled.first.c_str()))
|
||||
continue;
|
||||
else
|
||||
{ // if funcInfo was not found assume func to be impure
|
||||
loopCheckResults.hasImpureCalls = true;
|
||||
loopCheckResults.usesIO = true;
|
||||
loopCheckResults.linesOfIO.push_back(nameAndLineOfFuncCalled.second);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!calledFuncInfo->isPure)
|
||||
loopCheckResults.hasImpureCalls = true;
|
||||
|
||||
if (calledFuncInfo->usesIO())
|
||||
{
|
||||
loopCheckResults.usesIO = true;
|
||||
loopCheckResults.linesOfIO.push_back(nameAndLineOfFuncCalled.second);
|
||||
}
|
||||
}
|
||||
return loopCheckResults;
|
||||
}
|
||||
30
Sapfor/_src/DvmhRegions/LoopChecker.h
Normal file
30
Sapfor/_src/DvmhRegions/LoopChecker.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GraphLoop/graph_loops_func.h"
|
||||
#include "../GraphCall/graph_calls_func.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
struct LoopCheckResults
|
||||
{
|
||||
bool usesIO;
|
||||
bool hasImpureCalls;
|
||||
|
||||
std::vector<int> linesOfIO;
|
||||
|
||||
LoopCheckResults() : usesIO(false), hasImpureCalls(false) { }
|
||||
LoopCheckResults(bool io, bool calls) : usesIO(io), hasImpureCalls(calls) { }
|
||||
};
|
||||
|
||||
class LoopChecker
|
||||
{
|
||||
std::vector<LoopGraph*> &loopGraph;
|
||||
|
||||
LoopCheckResults checkLoopForPurenessAndIO(const LoopGraph *loopNode, const std::map<std::string, FuncInfo*> &allFuncs) const;
|
||||
LoopCheckResults updateLoopNode(LoopGraph *loop, const std::map<std::string, FuncInfo*> &allFuncs);
|
||||
public:
|
||||
explicit LoopChecker(std::vector<LoopGraph*> &graph) : loopGraph(graph) { }
|
||||
void updateLoopGraph(const std::map<std::string, FuncInfo*> &allFuncs);
|
||||
};
|
||||
341
Sapfor/_src/DvmhRegions/ReadWriteAnalyzer.cpp
Normal file
341
Sapfor/_src/DvmhRegions/ReadWriteAnalyzer.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
#include "leak_detector.h"
|
||||
#include "ReadWriteAnalyzer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void ReadWriteAnalyzer::init(SgFile* forFile)
|
||||
{
|
||||
auto save = current_file->filename();
|
||||
|
||||
modified_pars = ReadWriteAnalyzer::load_modified_pars(funcInfo);
|
||||
for (int j = 0; j < forFile->numberOfFunctions(); ++j)
|
||||
{
|
||||
SgStatement* func_hdr = forFile->functions(j);
|
||||
SgStatement* last = func_hdr->lastNodeOfStmt();
|
||||
|
||||
for (SgStatement* runner = func_hdr->lexNext(); runner != last; runner = runner->lexNext())
|
||||
{
|
||||
// TODO: is it ok to skip all of them?
|
||||
if (!isSgExecutableStatement(runner) || isDVM_stat(runner) || isSPF_stat(runner))
|
||||
continue;
|
||||
|
||||
if (runner->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
VarUsages usages = findUsagesInStatement(runner);
|
||||
|
||||
auto it = usages_by_statement.find(runner);
|
||||
if (it != usages_by_statement.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
usages_by_statement[runner] = usages;
|
||||
}
|
||||
}
|
||||
initialized.insert(forFile->filename());
|
||||
|
||||
if (SgFile::switchToFile(save) == -1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::findUsagesInStatement(SgStatement* st) const
|
||||
{
|
||||
// *special* statements, TODO: what i've missed?
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
return findUsagesInAssignment(st);
|
||||
|
||||
if (st->variant() == PROC_STAT)
|
||||
return findUsagesInFuncCall(st->expr(0), st->symbol()->identifier());
|
||||
else if (!isDVM_stat(st) && !isSPF_stat(st))
|
||||
{
|
||||
VarUsages st_usages;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
st_usages.extend(findUsagesInExpr(st->expr(i)));
|
||||
return st_usages;
|
||||
}
|
||||
return VarUsages();
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::findUsagesInAssignment(SgStatement* st) const
|
||||
{
|
||||
// load read & writes from the right part
|
||||
VarUsages usages = findUsagesInExpr(st->expr(1));
|
||||
|
||||
// load usages from array indexes
|
||||
VarUsages usages_in_arr_indexing = findUsagesInExpr(st->expr(1)->lhs());
|
||||
usages.extend(usages_in_arr_indexing);
|
||||
|
||||
usages_in_arr_indexing = findUsagesInExpr(st->expr(1)->rhs());
|
||||
usages.extend(usages_in_arr_indexing);
|
||||
|
||||
usages_in_arr_indexing = findUsagesInExpr(st->expr(0)->lhs());
|
||||
usages.extend(usages_in_arr_indexing);
|
||||
|
||||
usages_in_arr_indexing = findUsagesInExpr(st->expr(0)->rhs());
|
||||
usages.extend(usages_in_arr_indexing);
|
||||
|
||||
// finally add explicitly modified var
|
||||
auto ex = st->expr(0);
|
||||
auto s = st->expr(0)->symbol();
|
||||
if (s && (ex->variant() == VAR_REF || isArrayRef(ex)))
|
||||
usages.insert_write(ex);
|
||||
|
||||
return usages;
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::findUsagesInExpr(SgExpression* exp) const
|
||||
{
|
||||
VarUsages usages;
|
||||
|
||||
queue<SgExpression*> buf;
|
||||
buf.push(exp);
|
||||
|
||||
while (!buf.empty())
|
||||
{
|
||||
SgExpression* cur = buf.front();
|
||||
buf.pop();
|
||||
|
||||
if (!cur)
|
||||
continue;
|
||||
|
||||
const int e_type = cur->variant();
|
||||
|
||||
if (e_type == VAR_REF || isArrayRef(cur))
|
||||
usages.insert_read(cur);
|
||||
else if (e_type == FUNC_CALL)
|
||||
usages.extend(findUsagesInFuncCall(cur->lhs(), cur->symbol()->identifier()));
|
||||
|
||||
buf.push(cur->lhs());
|
||||
buf.push(cur->rhs());
|
||||
}
|
||||
return usages;
|
||||
}
|
||||
|
||||
void ReadWriteAnalyzer::findReadUsagesInExpression(SgExpression* ex, VarUsages& usages) const
|
||||
{
|
||||
if (ex)
|
||||
{
|
||||
if (ex->variant() == VAR_REF || ex->variant() == ARRAY_REF)
|
||||
usages.insert_read(ex);
|
||||
|
||||
findReadUsagesInExpression(ex->lhs(), usages);
|
||||
findReadUsagesInExpression(ex->rhs(), usages);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: need to improve to MPI_* functions
|
||||
VarUsages ReadWriteAnalyzer::findUsagesInFuncCall(SgExpression* params_tree, const string& func_key) const
|
||||
{
|
||||
VarUsages usages;
|
||||
|
||||
vector<int> inOutTypes;
|
||||
bool isIntrinsic = isIntrinsicFunctionName(func_key.c_str());
|
||||
if (!isIntrinsic)
|
||||
{
|
||||
auto it = modified_pars.find(func_key);
|
||||
if (it != modified_pars.end())
|
||||
inOutTypes = it->second;
|
||||
}
|
||||
else if (isMpiFunction(func_key.c_str()))
|
||||
{
|
||||
if (func_key == "mpi_abort")
|
||||
inOutTypes = { IN_BIT, IN_BIT, OUT_BIT };
|
||||
if (func_key == "mpi_send")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
if (func_key == "mpi_isend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_recv")
|
||||
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_irecv")
|
||||
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_alltoall")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_alltoallv")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_allgather")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_allgatherv")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_allreduce")
|
||||
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_reduce")
|
||||
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_reduce_scatter")
|
||||
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_scatter")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_scatterv")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_gather")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_gatherv")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_sendrecv")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_sendrecv_replace")
|
||||
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_scan")
|
||||
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_bcast")
|
||||
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_bsend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT };
|
||||
else if (func_key == "mpi_bsend_init")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_ibsend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_irsend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_issend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_recv_init")
|
||||
inOutTypes = { OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_rsend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT };
|
||||
else if (func_key == "mpi_rsend_init")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_send_init")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_ssend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT };
|
||||
else if (func_key == "mpi_ssend_init")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
}
|
||||
|
||||
int param_no = 0;
|
||||
while (params_tree)
|
||||
{
|
||||
SgExpression* param = params_tree->lhs();
|
||||
|
||||
if (param->variant() == VAR_REF || isArrayRef(param))
|
||||
{
|
||||
if (inOutTypes.size())
|
||||
{
|
||||
if (param_no >= inOutTypes.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (FuncParam::isArgIn((int64_t)inOutTypes[param_no]))
|
||||
usages.insert_read(param);
|
||||
if (FuncParam::isArgOut((int64_t)inOutTypes[param_no]))
|
||||
usages.insert_write(param);
|
||||
}
|
||||
else
|
||||
{
|
||||
usages.insert_read(param);
|
||||
if (!isIntrinsic)
|
||||
usages.insert_write(param);
|
||||
}
|
||||
|
||||
findReadUsagesInExpression(param->lhs(), usages);
|
||||
findReadUsagesInExpression(param->rhs(), usages);
|
||||
}
|
||||
|
||||
param_no++;
|
||||
params_tree = params_tree->rhs();
|
||||
}
|
||||
|
||||
return usages;
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::get_usages(SgStatement* st)
|
||||
{
|
||||
if (initialized.find(st->fileName()) == initialized.end())
|
||||
init(st->getFile());
|
||||
|
||||
VarUsages usages;
|
||||
// if statement is compound
|
||||
if (compound_statements.find(st->variant()) != compound_statements.end())
|
||||
usages = gatherUsagesForCompound(st);
|
||||
else
|
||||
{
|
||||
auto it = usages_by_statement.find(st);
|
||||
if (it == usages_by_statement.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
usages = it->second;
|
||||
}
|
||||
|
||||
return usages;
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::get_usages(vector<SgStatement*> &statements)
|
||||
{
|
||||
auto usages = VarUsages();
|
||||
|
||||
for (auto& st : statements)
|
||||
{
|
||||
auto st_usages = get_usages(st);
|
||||
usages.extend(st_usages);
|
||||
}
|
||||
return usages;
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::gatherUsagesForCompound(SgStatement* compoundStatement) const
|
||||
{
|
||||
VarUsages all_usages;
|
||||
|
||||
SgStatement* last = compoundStatement->lastNodeOfStmt();
|
||||
SgStatement* runner = compoundStatement;
|
||||
while (runner != last)
|
||||
{
|
||||
if (runner->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (!isSgExecutableStatement(runner) || isDVM_stat(runner) || isSPF_stat(runner))
|
||||
{
|
||||
runner = runner->lexNext();
|
||||
continue;
|
||||
}
|
||||
|
||||
all_usages.extend(findUsagesInStatement(runner));
|
||||
runner = runner->lexNext();
|
||||
}
|
||||
return all_usages;
|
||||
}
|
||||
|
||||
void ReadWriteAnalyzer::print() const
|
||||
{
|
||||
auto save = current_file->filename();
|
||||
|
||||
for (int i = 0; i < CurrentProject->numberOfFiles(); i++)
|
||||
{
|
||||
printf("file: %s\n", CurrentProject->file(i).filename());
|
||||
for (int j = 0; j < CurrentProject->file(i).numberOfFunctions(); j++)
|
||||
{
|
||||
printf("function: %s\n", CurrentProject->file(i).functions(j)->symbol()->identifier());
|
||||
SgStatement* runner = CurrentProject->file(i).functions(j);
|
||||
auto last = runner->lastNodeOfStmt();
|
||||
|
||||
while (runner != last)
|
||||
{
|
||||
if (runner->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
auto it = usages_by_statement.find(runner);
|
||||
if (it != usages_by_statement.end())
|
||||
{
|
||||
runner->unparsestdout();
|
||||
it->second.print();
|
||||
}
|
||||
runner = runner->lexNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SgFile::switchToFile(save) == -1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
map<string, vector<int>> ReadWriteAnalyzer::load_modified_pars(const map<string, vector<FuncInfo*>> &files)
|
||||
{
|
||||
map<string, vector<int>> res;
|
||||
|
||||
for (auto& funcs : files)
|
||||
{
|
||||
string file_name = funcs.first;
|
||||
|
||||
for (auto& func : funcs.second)
|
||||
{
|
||||
string func_key = func->funcName;
|
||||
res[func_key] = func->funcParams.inout_types;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
44
Sapfor/_src/DvmhRegions/ReadWriteAnalyzer.h
Normal file
44
Sapfor/_src/DvmhRegions/ReadWriteAnalyzer.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "dvm.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "VarUsages.h"
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
|
||||
|
||||
class ReadWriteAnalyzer
|
||||
{
|
||||
std::map<std::string, std::vector<FuncInfo*>> &funcInfo; // TODO: could be not initilized; should be rebuilt on invalidate()
|
||||
std::map<std::string, std::vector<int>> modified_pars; // func -> used for [in, inout, out] params,
|
||||
std::map<SgStatement*, VarUsages> usages_by_statement; // maps statements to variables used in them
|
||||
|
||||
std::set<std::string> initialized; // files was inited
|
||||
void init(SgFile*);
|
||||
|
||||
VarUsages findUsagesInStatement(SgStatement* st) const;
|
||||
VarUsages findUsagesInAssignment(SgStatement* st) const;
|
||||
void findReadUsagesInExpression(SgExpression* ex, VarUsages& toExtend) const;
|
||||
|
||||
const std::set<int> compound_statements = { FOR_NODE, LOOP_NODE, FUNC_HEDR, PROC_HEDR };
|
||||
VarUsages gatherUsagesForCompound(SgStatement* st) const;
|
||||
public:
|
||||
explicit ReadWriteAnalyzer(std::map<std::string, std::vector<FuncInfo*>> &funcInfo) : funcInfo(funcInfo)
|
||||
{ }
|
||||
|
||||
void invalidate(const std::string& fileName) { initialized.erase(fileName); }
|
||||
|
||||
VarUsages get_usages(SgStatement*);
|
||||
VarUsages get_usages(std::vector<SgStatement*>&);
|
||||
|
||||
VarUsages findUsagesInExpr(SgExpression* exp) const;
|
||||
VarUsages findUsagesInFuncCall(SgExpression*, const std::string&) const;
|
||||
|
||||
void print() const;
|
||||
|
||||
static std::map<std::string, std::vector<int>> load_modified_pars(const std::map<std::string, std::vector<FuncInfo*>>&);
|
||||
};
|
||||
195
Sapfor/_src/DvmhRegions/RegionsMerger.cpp
Normal file
195
Sapfor/_src/DvmhRegions/RegionsMerger.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include "leak_detector.h"
|
||||
#include "RegionsMerger.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool RegionsMerger::compareByStart(const DvmhRegion *a, const DvmhRegion *b)
|
||||
{
|
||||
if (a->getLoops().size() < 1 || b->getLoops().size() < 1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
int lineLeft = a->getLoops()[0]->lineNum;
|
||||
if (lineLeft < 0)
|
||||
lineLeft = a->getLoops()[0]->altLineNum;
|
||||
|
||||
int lineRight = b->getLoops()[0]->lineNum;
|
||||
if (lineRight < 0)
|
||||
lineRight = b->getLoops()[0]->altLineNum;
|
||||
return lineLeft < lineRight;
|
||||
}
|
||||
|
||||
bool RegionsMerger::canBeMoved(SgStatement* st, const DvmhRegion *region) const
|
||||
{
|
||||
// For now: st [a, d = b + c] can be moved IF [b, c] are not modified in region AND [a, d] not used for read in region
|
||||
// get usages for statement
|
||||
VarUsages st_usages = rw_analyzer.get_usages(st);
|
||||
|
||||
// get usages for region
|
||||
auto loop_statements = vector<SgStatement*>();
|
||||
for (auto& loop : region->getLoops())
|
||||
loop_statements.push_back(loop->loop);
|
||||
|
||||
auto region_usages = rw_analyzer.get_usages(loop_statements);
|
||||
|
||||
// analyze if statement can be placed before region
|
||||
if (sets_intersect(st_usages.get_reads(), region_usages.get_writes())) // check that [b, c] not modified in region
|
||||
return false;
|
||||
|
||||
if (sets_intersect(st_usages.get_writes(), region_usages.get_reads())) // check that [a, d] not read in region
|
||||
return false;
|
||||
|
||||
return true; // everything's ok
|
||||
}
|
||||
|
||||
vector<SgStatement*> RegionsMerger::getStatementsToMove(const DvmhRegion *first, const DvmhRegion *second, bool &can) const
|
||||
{
|
||||
// can not, abort operation
|
||||
if (first->getFileName() != second->getFileName() || first->getFunName() != second->getFunName())
|
||||
{
|
||||
can = false;
|
||||
return vector<SgStatement*>();
|
||||
}
|
||||
|
||||
vector<SgStatement*> toMove;
|
||||
SgStatement* mediumSt = first->getLastSt()->lexNext();
|
||||
|
||||
// skip DVM PARALLEL and hidden stats
|
||||
while (mediumSt->variant() == DVM_PARALLEL_ON_DIR || mediumSt->variant() < 0)
|
||||
mediumSt = mediumSt->lexNext();
|
||||
|
||||
//no statements between regions, so can
|
||||
if (mediumSt == second->getFirstSt() && mediumSt->variant() == FOR_NODE)
|
||||
{
|
||||
can = true;
|
||||
return vector<SgStatement*>();
|
||||
} //TODO
|
||||
else
|
||||
{
|
||||
can = false;
|
||||
return vector<SgStatement*>();
|
||||
}
|
||||
|
||||
//TODO: need to check and correct
|
||||
while (mediumSt->id() != second->getFirstSt()->id())
|
||||
{
|
||||
if (mediumSt->variant() == DVM_PARALLEL_ON_DIR)
|
||||
{
|
||||
mediumSt = mediumSt->lexNext();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (canBeMoved(mediumSt, first))
|
||||
toMove.push_back(mediumSt);
|
||||
else // can not, abort operation
|
||||
{
|
||||
can = false;
|
||||
return vector<SgStatement*>();
|
||||
}
|
||||
mediumSt = mediumSt->lexNext();
|
||||
}
|
||||
|
||||
return toMove;
|
||||
}
|
||||
|
||||
// Places statements before region
|
||||
void RegionsMerger::moveStatements(const vector<SgStatement*>& sts, const DvmhRegion* region)
|
||||
{
|
||||
SgStatement* prev = region->getFirstSt()->lexPrev();
|
||||
while (isDVM_stat(prev))
|
||||
prev = prev->lexPrev();
|
||||
|
||||
for (auto& st : sts)
|
||||
{
|
||||
SgStatement *toInsert = st->copyPtr();
|
||||
prev->insertStmtAfter(*toInsert, *prev->controlParent());
|
||||
prev = toInsert;
|
||||
st->deleteStmt();
|
||||
}
|
||||
|
||||
rw_analyzer.invalidate(region->getFileName());
|
||||
}
|
||||
|
||||
vector<DvmhRegion*> RegionsMerger::mergeRegions()
|
||||
{
|
||||
if (regions.size() < 2)
|
||||
return regions;
|
||||
|
||||
map<string, map<int, DvmhRegion*>> byFunc;
|
||||
for (auto& elem : regions)
|
||||
{
|
||||
const int line = elem->getLineForSort();
|
||||
const string fName = elem->getFunName();
|
||||
auto& itF = byFunc[fName];
|
||||
if (itF.find(line) != itF.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
itF[line] = elem;
|
||||
}
|
||||
|
||||
vector<DvmhRegion*> newRegions;
|
||||
|
||||
for (auto& regsForFunc : byFunc)
|
||||
{
|
||||
map<int, DvmhRegion*>& regionsByFunc = regsForFunc.second;
|
||||
|
||||
if (regionsByFunc.size() == 0)
|
||||
continue;
|
||||
|
||||
DvmhRegion* newRegion = new DvmhRegion();
|
||||
DvmhRegion* regionPrev = regionsByFunc.begin()->second;
|
||||
|
||||
bool isFirst = true;
|
||||
for (auto& loop : regionPrev->getLoops())
|
||||
newRegion->addLoop(loop);
|
||||
|
||||
for (auto& region : regionsByFunc)
|
||||
{
|
||||
if (newRegion->getFunName() == "" && region.second->getLoops().size() > 0)
|
||||
{
|
||||
SgStatement* func_st = getFuncStat(region.second->getLoops()[0]->loop);
|
||||
string fun_name = func_st->symbol()->identifier();
|
||||
newRegion->setFunName(fun_name);
|
||||
}
|
||||
|
||||
if (isFirst) // skip first region
|
||||
{
|
||||
isFirst = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool can = true;
|
||||
auto toMove = getStatementsToMove(regionPrev, region.second, can);
|
||||
if (can)
|
||||
{
|
||||
//TODO
|
||||
if (toMove.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
// moveStatements(toMove, regionPrev);
|
||||
}
|
||||
else
|
||||
{
|
||||
__spf_print(1, " region before loop on line %d (alt %d) cannot be merged\n",
|
||||
region.second->getLoops()[0]->lineNum, region.second->getLoops()[0]->altLineNum);
|
||||
toMove = getStatementsToMove(regionPrev, region.second, can);
|
||||
newRegions.push_back(newRegion);
|
||||
newRegion = new DvmhRegion();
|
||||
}
|
||||
|
||||
newRegion->append(*region.second);
|
||||
regionPrev = region.second;
|
||||
}
|
||||
newRegions.push_back(newRegion);
|
||||
}
|
||||
|
||||
for (auto& old : regions)
|
||||
delete old;
|
||||
regions.clear();
|
||||
return newRegions;
|
||||
}
|
||||
|
||||
bool RegionsMerger::sets_intersect(const set<SgSymbol*>& set1, const set<SgSymbol*>& set2) const
|
||||
{
|
||||
for (auto& symb : set1)
|
||||
if (set2.find(symb) != set2.end())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
19
Sapfor/_src/DvmhRegions/RegionsMerger.h
Normal file
19
Sapfor/_src/DvmhRegions/RegionsMerger.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#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();
|
||||
};
|
||||
36
Sapfor/_src/DvmhRegions/TypedSymbol.cpp
Normal file
36
Sapfor/_src/DvmhRegions/TypedSymbol.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "leak_detector.h"
|
||||
#include "TypedSymbol.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
TypedSymbol::TypedSymbol(SgExpression* orig_exp)
|
||||
{
|
||||
if (orig_exp->variant() == VAR_REF || orig_exp->variant() == ARRAY_REF)
|
||||
orig = OriginalSymbol(orig_exp->symbol());
|
||||
|
||||
type = VAR_TYPE::VAR_UNDEFINED;
|
||||
|
||||
if (orig_exp->variant() == VAR_REF)
|
||||
type = VAR_TYPE::VAR_SCALAR;
|
||||
|
||||
if (orig_exp->variant() == ARRAY_REF)
|
||||
{
|
||||
type = VAR_TYPE::VAR_ARR;
|
||||
DIST::Array* arr = getArrayFromDeclarated(declaratedInStmt(orig), orig->identifier());
|
||||
if (arr == NULL) //for strings charecter(*)
|
||||
type = VAR_TYPE::VAR_SCALAR;
|
||||
else if (!arr->IsNotDistribute())
|
||||
type = VAR_TYPE::VAR_DISTR_ARR;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator== (const TypedSymbol& lhs, const TypedSymbol& rhs)
|
||||
{
|
||||
return string(OriginalSymbol(lhs.orig)->identifier()) == string(OriginalSymbol(rhs.orig)->identifier()) &&
|
||||
OriginalSymbol(lhs.orig)->scope()->id() == OriginalSymbol(rhs.orig)->scope()->id();
|
||||
}
|
||||
|
||||
bool operator< (const TypedSymbol& lhs, const TypedSymbol& rhs)
|
||||
{
|
||||
return OriginalSymbol(lhs.orig)->id() < OriginalSymbol(rhs.orig)->id();
|
||||
}
|
||||
18
Sapfor/_src/DvmhRegions/TypedSymbol.h
Normal file
18
Sapfor/_src/DvmhRegions/TypedSymbol.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "dvm.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include <string>
|
||||
|
||||
enum class VAR_TYPE { VAR_ARR, VAR_DISTR_ARR, VAR_SCALAR, VAR_ANY, VAR_UNDEFINED };
|
||||
|
||||
class TypedSymbol
|
||||
{
|
||||
public:
|
||||
SgSymbol* orig;
|
||||
VAR_TYPE type;
|
||||
|
||||
TypedSymbol(SgExpression*);
|
||||
friend bool operator== (const TypedSymbol& lhs, const TypedSymbol& rhs);
|
||||
friend bool operator< (const TypedSymbol& lhs, const TypedSymbol& rhs);
|
||||
};
|
||||
97
Sapfor/_src/DvmhRegions/VarUsages.cpp
Normal file
97
Sapfor/_src/DvmhRegions/VarUsages.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "leak_detector.h"
|
||||
#include "VarUsages.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void VarUsages::extend(const VarUsages& to_insert)
|
||||
{
|
||||
undefined |= to_insert.undefined;
|
||||
|
||||
reads.insert(to_insert.reads.begin(), to_insert.reads.end());
|
||||
writes.insert(to_insert.writes.begin(), to_insert.writes.end());
|
||||
}
|
||||
|
||||
set<SgSymbol*> VarUsages::get_reads(const set<VAR_TYPE> var_type) const
|
||||
{
|
||||
if (undefined)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
return filter(reads, var_type);
|
||||
}
|
||||
|
||||
set<SgSymbol*> VarUsages::get_writes(const set<VAR_TYPE> var_type) const
|
||||
{
|
||||
if (undefined)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
return filter(writes, var_type);
|
||||
}
|
||||
|
||||
set<SgSymbol*> VarUsages::get_all(const set<VAR_TYPE> var_type) const
|
||||
{
|
||||
set<TypedSymbol> all_usages;
|
||||
all_usages.insert(reads.begin(), reads.end());
|
||||
all_usages.insert(writes.begin(), writes.end());
|
||||
|
||||
return filter(all_usages, var_type);
|
||||
}
|
||||
|
||||
set<SgSymbol*> VarUsages::get_reads() const { return get_reads({ VAR_TYPE::VAR_ANY }); }
|
||||
set<SgSymbol*> VarUsages::get_writes() const { return get_writes({ VAR_TYPE::VAR_ANY }); }
|
||||
set<SgSymbol*> VarUsages::get_all() const { return get_all({ VAR_TYPE::VAR_ANY }); }
|
||||
|
||||
set<SgSymbol*> VarUsages::filter(const set<TypedSymbol> &symbols, const set<VAR_TYPE> var_type)
|
||||
{
|
||||
set<SgSymbol*> filtered;
|
||||
if (var_type.find(VAR_TYPE::VAR_ANY) != var_type.end())
|
||||
for (auto& s : symbols)
|
||||
filtered.insert(s.orig);
|
||||
else
|
||||
for (auto& s : symbols)
|
||||
if (var_type.find(s.type) != var_type.end())
|
||||
filtered.insert(s.orig);
|
||||
return filtered;
|
||||
}
|
||||
|
||||
void VarUsages::insert_undefined(const TypedSymbol& s)
|
||||
{
|
||||
undefined = true;
|
||||
|
||||
reads.insert(s);
|
||||
writes.insert(s);
|
||||
}
|
||||
|
||||
void VarUsages::insert_read(const TypedSymbol& s) { reads.insert(s); }
|
||||
void VarUsages::insert_write(const TypedSymbol& s) { writes.insert(s); }
|
||||
|
||||
void VarUsages::print() const
|
||||
{
|
||||
printf("reads: ");
|
||||
if (undefined)
|
||||
printf("not_defined");
|
||||
else
|
||||
{
|
||||
for (auto& s : reads)
|
||||
printf("%s ", s.orig->identifier());
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("writes: ");
|
||||
if (undefined)
|
||||
printf("not_defined");
|
||||
else
|
||||
{
|
||||
for (auto& s : writes)
|
||||
printf("%s ", s.orig->identifier());
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("all: ");
|
||||
for (auto& s : get_all({ VAR_TYPE::VAR_ANY }))
|
||||
printf("%s ", s->identifier());
|
||||
printf("\n");
|
||||
|
||||
printf("***\n");
|
||||
}
|
||||
|
||||
bool VarUsages::is_undefined() const { return undefined; }
|
||||
33
Sapfor/_src/DvmhRegions/VarUsages.h
Normal file
33
Sapfor/_src/DvmhRegions/VarUsages.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "dvm.h"
|
||||
#include "TypedSymbol.h"
|
||||
#include <set>
|
||||
|
||||
|
||||
class VarUsages
|
||||
{
|
||||
std::set<TypedSymbol> reads;
|
||||
std::set<TypedSymbol> writes;
|
||||
bool undefined;
|
||||
|
||||
public:
|
||||
VarUsages() : undefined(false) { }
|
||||
void extend(const VarUsages&);
|
||||
|
||||
void insert_undefined(const TypedSymbol&);
|
||||
void insert_read(const TypedSymbol&);
|
||||
void insert_write(const TypedSymbol&);
|
||||
|
||||
bool is_undefined() const;
|
||||
std::set<SgSymbol*> get_reads(const std::set<VAR_TYPE>) const;
|
||||
std::set<SgSymbol*> get_writes(const std::set<VAR_TYPE>) const;
|
||||
std::set<SgSymbol*> get_all(const std::set<VAR_TYPE>) const;
|
||||
|
||||
std::set<SgSymbol*> get_reads() const;
|
||||
std::set<SgSymbol*> get_writes() const;
|
||||
std::set<SgSymbol*> get_all() const;
|
||||
|
||||
static std::set<SgSymbol*> filter(const std::set<TypedSymbol>&, const std::set<VAR_TYPE>);
|
||||
void print() const;
|
||||
};
|
||||
357
Sapfor/_src/DynamicAnalysis/createParallelRegions.cpp
Normal file
357
Sapfor/_src/DynamicAnalysis/createParallelRegions.cpp
Normal file
@@ -0,0 +1,357 @@
|
||||
#include "dvm.h"
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "./createParallelRegions.h"
|
||||
|
||||
#include "../CreateInterTree/CreateInterTree.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
#include "./gcov_info.h"
|
||||
#include "./gCov_parser_func.h"
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using std::string;
|
||||
using std::stack;
|
||||
using std::pair;
|
||||
using std::to_string;
|
||||
|
||||
static void markNestedIntervals(SpfInterval *interval)
|
||||
{
|
||||
for (auto &item : interval->nested)
|
||||
{
|
||||
item->isNested = true;
|
||||
|
||||
if (!item->begin->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (item->begin->symbol()->identifier() != NULL)
|
||||
markNestedIntervals(item);
|
||||
}
|
||||
}
|
||||
|
||||
static int countOfIntervals(const SpfInterval *interval, const SpfInterval *mainInterval)
|
||||
{
|
||||
int count = 0;
|
||||
for (auto &item : mainInterval->nested)
|
||||
{
|
||||
if (item == interval)
|
||||
count++;
|
||||
else
|
||||
count += countOfIntervals(interval, item);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void performFuncTime(const map<string, vector<FuncInfo*>> &funcInfo, map<string, int> &countFunc)
|
||||
{
|
||||
int count = 0;
|
||||
for (auto &str : funcInfo)
|
||||
{
|
||||
count = 0;
|
||||
for (auto *info : str.second)
|
||||
{
|
||||
count += (info->callsTo).size();
|
||||
|
||||
if (countFunc.find(info->funcName) != countFunc.end())
|
||||
countFunc[info->funcName] += count;
|
||||
else
|
||||
countFunc.insert(make_pair(info->funcName, count));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double performTime(SgProject* project, SgStatement *src, const map<string, map<int, Gcov_info>> &gCovInfo, map<string, int> &calls, int recLevel)
|
||||
{
|
||||
SgStatement* stmt = src;
|
||||
|
||||
if (!src->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (!isSgExecutableStatement(stmt))
|
||||
return 0.0;
|
||||
|
||||
auto gCovForFile = gCovInfo.find(string(stmt->fileName()));
|
||||
if (gCovForFile == gCovInfo.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
auto gCovForStmt = gCovForFile->second.find(stmt->lineNumber());
|
||||
if (gCovForStmt == gCovForFile->second.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
const Gcov_info& info = gCovForStmt->second;
|
||||
double count = 0.0;
|
||||
|
||||
switch (stmt->variant())
|
||||
{
|
||||
case PROC_STAT:
|
||||
{
|
||||
if (recLevel <= 5)
|
||||
{
|
||||
SgCallStmt *call = (SgCallStmt*)src;
|
||||
if (info.getCountCalls() == 0)
|
||||
break;
|
||||
SgStatement *body = NULL;
|
||||
string funcName(call->name()->identifier());
|
||||
auto num = calls.find(funcName);
|
||||
// its not a user function
|
||||
if (num == calls.end())
|
||||
break;
|
||||
|
||||
for (int j = 0; j < project->numberOfFiles(); ++j)
|
||||
{
|
||||
SgFile& file = project->file(j);
|
||||
if (SgFile::switchToFile(file.filename()) == -1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (int i = 0; i < file.numberOfFunctions(); ++i)
|
||||
{
|
||||
if (!strcmp(file.functions(i)->symbol()->identifier(), funcName.c_str()))
|
||||
{
|
||||
body = file.functions(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (body == NULL)
|
||||
break;
|
||||
|
||||
while (body && body->variant() != RETURN_STAT)
|
||||
{
|
||||
count += performTime(project, body, gCovInfo, calls, recLevel + 1);
|
||||
|
||||
if (!body->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
body = body->lexNext();
|
||||
}
|
||||
|
||||
count /= num->second;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IF_NODE:
|
||||
case LOGIF_NODE:
|
||||
case ELSEIF_NODE:
|
||||
{
|
||||
SgIfStmt* ifSt = (SgIfStmt*)src;
|
||||
SgStatement* tmp = ifSt->trueBody();
|
||||
int t = 0;
|
||||
while (tmp->variant() != CONTROL_END)
|
||||
{
|
||||
t += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
|
||||
tmp = tmp->lexNext();
|
||||
}
|
||||
count += (info.getBranches()[0].getPercent()) * 0.01 * t;
|
||||
t = 0;
|
||||
tmp = ifSt->falseBody();
|
||||
while (tmp && tmp->variant() != CONTROL_END)
|
||||
{
|
||||
t += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
|
||||
tmp = tmp->lexNext();
|
||||
}
|
||||
count += (info.getBranches()[1].getPercent()) * 0.01 * t;
|
||||
break;
|
||||
}
|
||||
case WHILE_NODE:
|
||||
{
|
||||
SgWhileStmt* whileSt = (SgWhileStmt*)src;
|
||||
SgStatement* tmp = whileSt->body();
|
||||
while (tmp->variant() != CONTROL_END)
|
||||
{
|
||||
count += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
|
||||
|
||||
if (!tmp->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
tmp = tmp->lexNext();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FOR_NODE:
|
||||
{
|
||||
SgForStmt* forSt = (SgForStmt*)src;
|
||||
SgStatement* tmp = forSt->body();
|
||||
while (tmp->variant() != CONTROL_END)
|
||||
{
|
||||
count += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
|
||||
|
||||
if (!tmp->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
tmp = tmp->lexNext();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADD_OP:
|
||||
case MULT_OP:
|
||||
case DIV_OP:
|
||||
case SUB_OP:
|
||||
case ASSGN_OP:
|
||||
case ASSIGN_STAT:
|
||||
// let frequency be about 2 GHerz
|
||||
count += 0.0000000005 * info.getExecutedCount();
|
||||
break;
|
||||
case WRITE_STAT:
|
||||
case READ_STAT:
|
||||
// read/write operations are slower
|
||||
count += 0.0000000015 * info.getExecutedCount();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
typedef pair<vector<SpfInterval*>, int> PositionInVector;
|
||||
typedef stack<PositionInVector> IntervalStack;
|
||||
|
||||
double performIntervalTime(SgProject* project, const SpfInterval *interval, const map<string, map<int, Gcov_info>> &gCovInfo, map<string, int> &calls)
|
||||
{
|
||||
double time = 0.0;
|
||||
for (SgStatement *stat = interval->begin; stat != interval->ends[interval->ends.size() - 1]; stat = stat->lexNext())
|
||||
{
|
||||
time += performTime(project, stat, gCovInfo, calls, 0);
|
||||
if (!stat->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
void createParallelRegions(SgProject* project, SpfInterval *mainInterval, const map<string, map<int, Gcov_info>> &gCovInfo, const map<string, vector<FuncInfo*>> &funcInfo)
|
||||
{
|
||||
double percent = 0.8;
|
||||
vector<SpfRegion> regions;
|
||||
map<string, int> calls;
|
||||
|
||||
performFuncTime(funcInfo, calls);
|
||||
if (mainInterval == NULL)
|
||||
{
|
||||
__spf_print(1, "internal error in analysis, directives will not be generated for this file!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
double sumTime = performIntervalTime(project, mainInterval, gCovInfo, calls);
|
||||
|
||||
double alreadyHavePercent = 0.0;
|
||||
int id = 1;
|
||||
int i = 0;
|
||||
IntervalStack stack;
|
||||
vector<SpfInterval*> iterated;
|
||||
vector<SpfInterval*> nested;
|
||||
|
||||
iterated.push_back(mainInterval);
|
||||
|
||||
while (alreadyHavePercent <= percent)
|
||||
{
|
||||
if (i >= iterated.size())
|
||||
{
|
||||
if (!stack.empty())
|
||||
{
|
||||
iterated = stack.top().first;
|
||||
i = stack.top().second;
|
||||
|
||||
stack.pop();
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
SpfInterval* interval = iterated[i];
|
||||
if (!interval || interval->isRegion || interval->isNested)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
double time = performIntervalTime(project, interval, gCovInfo, calls);
|
||||
int count = countOfIntervals(interval, mainInterval);
|
||||
if (count != 0) time *= count;
|
||||
double percentOfInterval = time / sumTime;
|
||||
|
||||
if (percentOfInterval + alreadyHavePercent <= percent)
|
||||
{
|
||||
__spf_print(1, "Add interval with %f percent, we have %f percent\n", percentOfInterval, percentOfInterval + alreadyHavePercent);
|
||||
SpfRegion region(id, time, interval->begin, interval->ends[0]);
|
||||
region.time = time;
|
||||
region.id = id;
|
||||
iterated[i]->isRegion = true;
|
||||
markNestedIntervals(interval);
|
||||
id++;
|
||||
i++;
|
||||
|
||||
regions.push_back(region);
|
||||
alreadyHavePercent += percentOfInterval;
|
||||
}
|
||||
else
|
||||
{
|
||||
__spf_print(1, "divide interval with %f percent\n", percentOfInterval);
|
||||
if (i < iterated.size() - 1)
|
||||
stack.push(make_pair(vector<SpfInterval*>(iterated.begin(), iterated.end()), i + 1));
|
||||
|
||||
iterated.clear();
|
||||
iterated = vector<SpfInterval*>(interval->nested.begin(), interval->nested.end());
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < regions.size())
|
||||
{
|
||||
if (i > 0 && !regions[i-1].end->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (i > 0 && regions[i - 1].end->lexNext() == regions[i].start)
|
||||
{
|
||||
regions[i - 1].end = regions[i].end;
|
||||
regions.erase(regions.begin() + i);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
__spf_print(1, "Coverage of region is %f percent, count of regions is %d\n", alreadyHavePercent, regions.size());
|
||||
|
||||
for (auto &item : regions)
|
||||
{
|
||||
if (!item.start->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
SgStatement *startRegion = new SgStatement(SPF_PARALLEL_REG_DIR);
|
||||
SgStatement *endRegion = new SgStatement(SPF_END_PARALLEL_REG_DIR);
|
||||
|
||||
startRegion->setSymbol(*(new SgSymbol(VARIABLE_NAME, to_string(item.id).c_str())));
|
||||
|
||||
SgStatement *st = item.start;
|
||||
while (!isSgExecutableStatement(st))
|
||||
st = st->lexNext();
|
||||
|
||||
startRegion->setFileId(st->getFileId());
|
||||
startRegion->setProject(st->getProject());
|
||||
startRegion->setlineNumber(st->lineNumber());
|
||||
startRegion->setFileName(st->fileName());
|
||||
|
||||
st->insertStmtBefore(*startRegion, *st->controlParent());
|
||||
|
||||
SgStatement *next = item.end->lexNext();
|
||||
startRegion->setFileId(next->getFileId());
|
||||
startRegion->setProject(next->getProject());
|
||||
startRegion->setlineNumber(next->lineNumber());
|
||||
startRegion->setFileName(next->fileName());
|
||||
|
||||
next->insertStmtBefore(*endRegion, *next->controlParent());
|
||||
}
|
||||
}
|
||||
34
Sapfor/_src/DynamicAnalysis/createParallelRegions.h
Normal file
34
Sapfor/_src/DynamicAnalysis/createParallelRegions.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Utils/utils.h"
|
||||
|
||||
#include "./gcov_info.h"
|
||||
#include "../CreateInterTree/CreateInterTree.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
struct SpfRegion
|
||||
{
|
||||
int id;
|
||||
|
||||
double time;
|
||||
SgStatement *start;
|
||||
SgStatement *end;
|
||||
|
||||
SpfRegion(int id_, int time_, SgStatement *start_, SgStatement *end_) :
|
||||
id(id_), time(time_), start(start_), end(end_) {}
|
||||
|
||||
SpfRegion& operator+=(const SpfRegion &rg)
|
||||
{
|
||||
if (this != &rg)
|
||||
{
|
||||
end = rg.end;
|
||||
time += rg.time;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
void createParallelRegions(SgProject *project, SpfInterval *mainInterval, const std::map<std::string, std::map<int, Gcov_info>> &gCovInfo, const std::map<std::string, std::vector<FuncInfo*>> &funcInfo);
|
||||
473
Sapfor/_src/DynamicAnalysis/gCov_parser.cpp
Normal file
473
Sapfor/_src/DynamicAnalysis/gCov_parser.cpp
Normal file
@@ -0,0 +1,473 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "dvm.h"
|
||||
#include "gCov_parser_func.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
enum key_word
|
||||
{
|
||||
UNKNOWN,
|
||||
BRANCH,
|
||||
CALL,
|
||||
};
|
||||
|
||||
static const char *key_words[] =
|
||||
{
|
||||
"",
|
||||
"branch",
|
||||
"call",
|
||||
"taken",
|
||||
"returned",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *symbols_neverExecuted[] =
|
||||
{
|
||||
"",
|
||||
"#####",
|
||||
"%%%%%",
|
||||
"$$$$$",
|
||||
"=====",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void isKeyWord(const string &lex, key_word &lineType)
|
||||
{
|
||||
int i = 1;
|
||||
bool find = false;
|
||||
while ((!find) && key_words[i]) {
|
||||
if (lex.compare(key_words[i]) == 0)
|
||||
find = true;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
switch (i) {
|
||||
case 1:
|
||||
lineType = BRANCH;
|
||||
break;
|
||||
case 2:
|
||||
lineType = CALL;
|
||||
break;
|
||||
default:
|
||||
if (lineType != UNKNOWN)
|
||||
{
|
||||
__spf_print(1, "Error: Wrong work of analysis keywords\n");
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool isNeverExecuted(const string &lex)
|
||||
{
|
||||
int i = 1;
|
||||
bool find = false;
|
||||
while ((!find) && symbols_neverExecuted[i])
|
||||
{
|
||||
if (lex.compare(symbols_neverExecuted[i]) == 0)
|
||||
find = true;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
return find;
|
||||
}
|
||||
|
||||
static void getInfo(map<int, Gcov_info> &info, const string &str)
|
||||
{
|
||||
Gcov_info infoLine;
|
||||
Perform infoPerform;
|
||||
string num, lex;
|
||||
key_word lineType = UNKNOWN;
|
||||
bool executedCountGot = false;
|
||||
int i = 0;
|
||||
int len = str.length();
|
||||
int minus = 0;
|
||||
int ddot = 0;
|
||||
while (i != len)
|
||||
{
|
||||
char c = str[i];
|
||||
if ((c >= 48) && (c <= 57)) //symbols '0'-'9'
|
||||
num.push_back(c);
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case ' ':
|
||||
if ((!lex.empty()) && (lineType == UNKNOWN))
|
||||
isKeyWord(lex, lineType);
|
||||
lex.clear();
|
||||
if ((!num.empty()) && ((lineType == BRANCH) || (lineType == CALL)))
|
||||
infoPerform.setNumber(stoi(num, nullptr));
|
||||
num.clear();
|
||||
break;
|
||||
case ':':
|
||||
ddot++;
|
||||
if ((!lex.empty()) && (isNeverExecuted(lex)))
|
||||
{
|
||||
executedCountGot = true;
|
||||
infoLine.setExecutedCount(0);
|
||||
}
|
||||
if (!num.empty())
|
||||
{
|
||||
if (!executedCountGot)
|
||||
{
|
||||
const int64_t value = stoll(num);
|
||||
if (minus == 1 && ddot == 1 && value == 0)
|
||||
infoLine.setExecutedCount(-1);
|
||||
else
|
||||
infoLine.setExecutedCount(value);
|
||||
executedCountGot = true;
|
||||
}
|
||||
else
|
||||
infoLine.setNumLine(stoi(num, nullptr));
|
||||
}
|
||||
num.clear();
|
||||
break;
|
||||
case '%':
|
||||
if (!num.empty())
|
||||
infoPerform.setPercent(stoi(num, nullptr));
|
||||
num.clear();
|
||||
break;
|
||||
case '-':
|
||||
minus++;
|
||||
num.push_back('0');
|
||||
break;
|
||||
default:
|
||||
//Try find 'branch' or 'call'
|
||||
lex.push_back(c);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (infoLine.getNumLine() != -1)
|
||||
info.insert(make_pair(infoLine.getNumLine(), infoLine));
|
||||
|
||||
switch (lineType)
|
||||
{
|
||||
case BRANCH:
|
||||
((*(info.rbegin())).second).setBranch(infoPerform);
|
||||
break;
|
||||
case CALL:
|
||||
((*(info.rbegin())).second).setCall(infoPerform);
|
||||
break;
|
||||
case UNKNOWN:
|
||||
break;
|
||||
default:
|
||||
__spf_print(1, "Error: get unreal type\n");
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void printPerform(map<int, Perform> info, ostream &myfile)
|
||||
{
|
||||
map<int, Perform>::iterator cur;
|
||||
for (cur = info.begin(); cur != info.end(); cur++)
|
||||
myfile << (*cur).first << ")" << (*cur).second;
|
||||
}
|
||||
|
||||
static void printInfo2file(map<int, Gcov_info> &info, ostream &myfile)
|
||||
{
|
||||
map<int, Gcov_info>::iterator cur;
|
||||
for (cur = info.begin(); cur != info.end(); cur++)
|
||||
{
|
||||
Gcov_info cur_gcov = (*cur).second;
|
||||
myfile << "_________________\n";
|
||||
myfile << "№" << (*cur).first << endl << cur_gcov;
|
||||
if (cur_gcov.getCountCalls() != 0)
|
||||
{
|
||||
myfile << "-----Calls----\n";
|
||||
printPerform(cur_gcov.getCalls(), myfile);
|
||||
}
|
||||
|
||||
if (cur_gcov.getCountBranches() != 0)
|
||||
{
|
||||
myfile << "----Branches----\n";
|
||||
printPerform(cur_gcov.getBranches(), myfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline string modify_name(const string &name)
|
||||
{
|
||||
return name + "_pgcov.txt";
|
||||
}
|
||||
|
||||
/*
|
||||
-добавить флаги при компиляции : gfortran -O2 -g -fprofile-arcs -ftest-coverage
|
||||
- запустить программу
|
||||
- отдать исходник профилировщику с флагом : LANG=en_US.utf8 gcov -b file.f
|
||||
*/
|
||||
|
||||
static void fixGcovInfo(SgFile *fileSg, map<int, Gcov_info> &gCovInfo)
|
||||
{
|
||||
for (SgStatement *st = fileSg->firstStatement(); st; st = st->lexNext())
|
||||
{
|
||||
if (isSgExecutableStatement(st) && !isDVM_stat(st) && !isSPF_stat(st) &&
|
||||
(st->variant() != DVM_INTERVAL_DIR && st->variant() != DVM_ENDINTERVAL_DIR))
|
||||
{
|
||||
auto next = st->lexNext();
|
||||
const int currLine = st->lineNumber();
|
||||
const int nextLine = next ? next->lineNumber() : -1;
|
||||
if (next)
|
||||
{
|
||||
if (nextLine == currLine)
|
||||
continue;
|
||||
|
||||
auto it = gCovInfo.find(currLine);
|
||||
|
||||
if (it != gCovInfo.end())
|
||||
{
|
||||
if (it->second.getExecutedCount() <= 0)
|
||||
{
|
||||
int nextL = currLine + 1;
|
||||
while (nextL != nextLine)
|
||||
{
|
||||
auto itNext = gCovInfo.find(nextL);
|
||||
if (itNext != gCovInfo.end())
|
||||
{
|
||||
if (itNext->second.getExecutedCount() >= 0)
|
||||
{
|
||||
it->second.clear();
|
||||
it->second.setExecutedCount(itNext->second.getExecutedCount());
|
||||
for (auto &call : itNext->second.getCalls())
|
||||
it->second.setCall(call.second);
|
||||
for (auto &branch : itNext->second.getBranches())
|
||||
it->second.setBranch(branch.second);
|
||||
|
||||
// copy to between
|
||||
for (int z = currLine + 1; z != nextL; ++z)
|
||||
{
|
||||
auto itZ = gCovInfo.find(z);
|
||||
if (itZ != gCovInfo.end())
|
||||
{
|
||||
itZ->second.clear();
|
||||
itZ->second.setExecutedCount(itNext->second.getExecutedCount());
|
||||
for (auto &call : itNext->second.getCalls())
|
||||
itZ->second.setCall(call.second);
|
||||
for (auto &branch : itNext->second.getBranches())
|
||||
itZ->second.setBranch(branch.second);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
nextL++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (SgStatement *st = fileSg->firstStatement(); st; st = st->lexNext())
|
||||
{
|
||||
if (isSgExecutableStatement(st) && !isDVM_stat(st) && !isSPF_stat(st) &&
|
||||
(st->variant() != DVM_INTERVAL_DIR && st->variant() != DVM_ENDINTERVAL_DIR))
|
||||
{
|
||||
if (st->variant() == CONTROL_END)
|
||||
{
|
||||
auto cp = st->controlParent();
|
||||
auto it = gCovInfo.find(cp->lineNumber());
|
||||
if (it != gCovInfo.end() && cp->variant() != PROG_HEDR &&
|
||||
cp->variant() != PROC_HEDR && cp->variant() != FUNC_HEDR &&
|
||||
isSgExecutableStatement(cp))
|
||||
{
|
||||
auto it = gCovInfo.find(st->lineNumber());
|
||||
auto itCp = gCovInfo.find(cp->lineNumber());
|
||||
if (it != gCovInfo.end())
|
||||
{
|
||||
it->second.clear();
|
||||
it->second.setExecutedCount(itCp->second.getExecutedCount());
|
||||
for (auto &call : itCp->second.getCalls())
|
||||
it->second.setCall(call.second);
|
||||
for (auto &branch : itCp->second.getBranches())
|
||||
it->second.setBranch(branch.second);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static map<string, map<int, Gcov_info>*> allGCovInfo;
|
||||
void parse_gcovfile(SgFile *fileSg, const string &basefileNameIn, map<int, Gcov_info> &gCovInfo, bool keep)
|
||||
{
|
||||
if (basefileNameIn == "")
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
else
|
||||
{
|
||||
const string basefileName = basefileNameIn + ".gcov";
|
||||
ifstream file;
|
||||
file.open(basefileName, ios::in);
|
||||
if (file.is_open())
|
||||
{
|
||||
string str;
|
||||
while (!file.eof())
|
||||
{
|
||||
getline(file, str);
|
||||
getInfo(gCovInfo, str);
|
||||
}
|
||||
file.close();
|
||||
fixGcovInfo(fileSg, gCovInfo);
|
||||
|
||||
if (keep)
|
||||
{
|
||||
// FOR DEBUG ONLY
|
||||
string name_f = modify_name(basefileName);
|
||||
ofstream myfile(name_f);
|
||||
if (myfile.is_open())
|
||||
printInfo2file(gCovInfo, myfile);
|
||||
else
|
||||
__spf_print(1, " Error: unable to create file %s\n", name_f.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
__spf_print(1, " Error: unable to open file %s\n", basefileName.c_str());
|
||||
}
|
||||
allGCovInfo[fileSg->filename()] = &gCovInfo;
|
||||
}
|
||||
|
||||
bool __gcov_doesThisLineExecuted(const string &file, const int line)
|
||||
{
|
||||
bool ret = true;
|
||||
auto itF = allGCovInfo.find(file);
|
||||
if (itF != allGCovInfo.end())
|
||||
{
|
||||
auto itL = itF->second->find(line);
|
||||
if (itL != itF->second->end())
|
||||
ret = itL->second.getExecutedCount() != 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
pair<int, int64_t> __gcov_GetExecuted(const string &file, const int line)
|
||||
{
|
||||
pair<int, int64_t> ret = make_pair(0, 0);
|
||||
auto itF = allGCovInfo.find(file);
|
||||
if (itF != allGCovInfo.end())
|
||||
{
|
||||
auto itL = itF->second->find(line);
|
||||
if (itL != itF->second->end())
|
||||
ret.second = itL->second.getExecutedCount();
|
||||
else
|
||||
ret.first = -1;
|
||||
}
|
||||
else
|
||||
ret.first = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void parseTimesDvmStatisticFile(const string &file, map<string, vector<SpfInterval*>> &intervals)
|
||||
{
|
||||
map<string, map<int, SpfInterval*>> mapOfIntervals;
|
||||
for (auto &intByfile : intervals)
|
||||
createMapOfinterval(mapOfIntervals[intByfile.first], intByfile.second);
|
||||
|
||||
FILE *stat = fopen(file.c_str(), "r");
|
||||
if (stat)
|
||||
{
|
||||
char buf[8192];
|
||||
int execDone = 1;
|
||||
int line = -1;
|
||||
string fileN = "";
|
||||
SpfInterval *curr = NULL;
|
||||
|
||||
while (!feof(stat))
|
||||
{
|
||||
char *read = fgets(buf, 8192, stat);
|
||||
if (read)
|
||||
{
|
||||
const string origLine(read);
|
||||
auto itF = origLine.find("INTERVAL");
|
||||
auto itTypeU = origLine.find("USER");
|
||||
auto itExpr = origLine.find("EXPR=");
|
||||
if (itF != string::npos && itTypeU != string::npos && itExpr != string::npos)
|
||||
{
|
||||
execDone = 0;
|
||||
line = -1;
|
||||
fileN = "";
|
||||
int expr = 0;
|
||||
curr = NULL;
|
||||
|
||||
auto itL = origLine.find("NLINE=");
|
||||
if (itL != string::npos)
|
||||
{
|
||||
string lineS = "";
|
||||
for (size_t z = itL + 6; origLine[z] != ' '; ++z)
|
||||
lineS += origLine[z];
|
||||
line = atoi(lineS.c_str());
|
||||
}
|
||||
|
||||
auto itS = origLine.find("SOURCE=");
|
||||
if (itS != string::npos)
|
||||
{
|
||||
string source = "";
|
||||
for (size_t z = itS + 7; origLine[z] != ' '; ++z)
|
||||
source += origLine[z];
|
||||
fileN = source;
|
||||
convertToLower(fileN);
|
||||
}
|
||||
|
||||
string exprS = "";
|
||||
for (size_t z = itExpr + 5; origLine[z] != '\n'; ++z)
|
||||
exprS += origLine[z];
|
||||
expr = atoi(exprS.c_str());
|
||||
|
||||
if (line != -1 && fileN != "")
|
||||
{
|
||||
auto itIntF = mapOfIntervals.find(fileN);
|
||||
if (itIntF == mapOfIntervals.end())
|
||||
{
|
||||
//TODO: error
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto &inter : itIntF->second)
|
||||
{
|
||||
if (inter.second->tag == expr)
|
||||
{
|
||||
curr = inter.second;
|
||||
string execCountS = "";
|
||||
auto itExec = origLine.find("EXE_COUNT=");
|
||||
string execS = "";
|
||||
for (size_t z = itExec + 10; origLine[z] != ' '; ++z)
|
||||
execS += origLine[z];
|
||||
inter.second->exec_count = atoi(execS.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto itE = origLine.find("Execution time");
|
||||
if (itE != string::npos && execDone == 0)
|
||||
{
|
||||
execDone = 1;
|
||||
size_t idx = 16;
|
||||
while (origLine[idx++] == ' ');
|
||||
string execC = "";
|
||||
for (size_t z = idx - 1; z < origLine.size(); ++z)
|
||||
execC += origLine[z];
|
||||
double execTime = atof(execC.c_str());
|
||||
|
||||
if (line != -1 && fileN != "" && curr)
|
||||
curr->exec_time += execTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(stat);
|
||||
}
|
||||
else
|
||||
__spf_print(1, " Error: unable to open file %s\n", file.c_str());
|
||||
}
|
||||
15
Sapfor/_src/DynamicAnalysis/gCov_parser_func.h
Normal file
15
Sapfor/_src/DynamicAnalysis/gCov_parser_func.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "dvm.h"
|
||||
#include "../Utils/errors.h"
|
||||
#include "gcov_info.h"
|
||||
#include "../CreateInterTree/CreateInterTree.h"
|
||||
|
||||
void parse_gcovfile(SgFile *file, const std::string &basefileName, std::map<int, Gcov_info> &gCovInfo, bool keep);
|
||||
bool __gcov_doesThisLineExecuted(const std::string &file, const int line);
|
||||
std::pair<int, int64_t> __gcov_GetExecuted(const std::string &file, const int line);
|
||||
void parseTimesDvmStatisticFile(const std::string &file, std::map<std::string, std::vector<SpfInterval*>> &intervals);
|
||||
48
Sapfor/_src/DynamicAnalysis/gcov_info.cpp
Normal file
48
Sapfor/_src/DynamicAnalysis/gcov_info.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../Utils/errors.h"
|
||||
|
||||
#include "gcov_info.h"
|
||||
|
||||
using std::map;
|
||||
using std::make_pair;
|
||||
using std::ostream;
|
||||
using std::endl;
|
||||
|
||||
Gcov_info::Gcov_info() { numLine = -1; executedCount = -1; countCalls = 0; countBranches = 0; }
|
||||
Gcov_info::Gcov_info(int a, int b) { numLine = a; executedCount = b; }
|
||||
|
||||
void Gcov_info::set(int a, int64_t b, int c, int d) { numLine = a; executedCount = b; countCalls = c; countBranches = d; }
|
||||
|
||||
int Gcov_info::getNumLine() const { return numLine; }
|
||||
int64_t Gcov_info::getExecutedCount() const { return executedCount; }
|
||||
void Gcov_info::setNumLine(int a) { numLine = a; }
|
||||
void Gcov_info::setExecutedCount(int64_t a) { executedCount = a; }
|
||||
void Gcov_info::setCall(Perform a) { countCalls++; calls.insert(make_pair(a.getNumber(), a)); }
|
||||
void Gcov_info::setBranch(Perform a) { countBranches++; branches.insert(make_pair(a.getNumber(), a)); }
|
||||
map<int, Perform> Gcov_info::getCalls() const { return calls; }
|
||||
map<int, Perform> Gcov_info::getBranches() const { return branches; }
|
||||
int Gcov_info::getCountCalls() const { return countCalls; }
|
||||
int Gcov_info::getCountBranches() const { return countBranches; }
|
||||
void Gcov_info::gcov_print() const { __spf_print(1, "%d - %lld\n", numLine, executedCount); }
|
||||
ostream &operator<<(ostream &out, const Gcov_info &a) {
|
||||
out << "numLine= " << a.numLine << "\nexecutedCount= " << a.executedCount <<
|
||||
"\ncountCalls= " << a.countCalls << "\ncountBranches= " << a.countBranches << endl;
|
||||
return out;
|
||||
}
|
||||
|
||||
//-------------------------Perform-----------------------------------------
|
||||
|
||||
Perform::Perform() { number = -1; percent = -1; }
|
||||
Perform::Perform(int a, int b) { number = a; percent = b; }
|
||||
void Perform::set(int a, int b) { number = a; percent = b; }
|
||||
int Perform::getNumber() { return number; }
|
||||
int Perform::getPercent() { return percent; }
|
||||
void Perform::setNumber(int a) { number = a; }
|
||||
void Perform::setPercent(int a) { percent = a; }
|
||||
void Perform::gcov_print() { __spf_print(1, "%d - %d\n", number, percent); }
|
||||
ostream &operator<<(ostream &out, const Perform &a) { out << "number= " << a.number << ": percent= " << a.percent << endl; return out; }
|
||||
53
Sapfor/_src/DynamicAnalysis/gcov_info.h
Normal file
53
Sapfor/_src/DynamicAnalysis/gcov_info.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../Utils/utils.h"
|
||||
|
||||
//make 'class' - need friend for Gcov_info
|
||||
struct Perform
|
||||
{
|
||||
int number;
|
||||
int percent;
|
||||
|
||||
Perform();
|
||||
Perform(int a, int b);
|
||||
void set(int a, int b);
|
||||
int getNumber();
|
||||
int getPercent();
|
||||
void setNumber(int a);
|
||||
void setPercent(int a);
|
||||
void gcov_print();
|
||||
friend std::ostream &operator<<(std::ostream &out, const Perform &a);
|
||||
};
|
||||
|
||||
class Gcov_info
|
||||
{
|
||||
int numLine;
|
||||
int64_t executedCount;
|
||||
int countCalls;
|
||||
std::map<int, Perform> calls;
|
||||
int countBranches;
|
||||
std::map<int, Perform> branches;
|
||||
|
||||
public:
|
||||
Gcov_info();
|
||||
Gcov_info(int a, int b);
|
||||
void set(int a, int64_t b, int c, int d);
|
||||
void clear() { calls.clear(); branches.clear(); countCalls = 0; countBranches = 0; }
|
||||
int getNumLine() const;
|
||||
int64_t getExecutedCount() const;
|
||||
void setNumLine(int a);
|
||||
void setExecutedCount(int64_t a);
|
||||
int getCountCalls() const;
|
||||
int getCountBranches() const;
|
||||
std::map<int,Perform> getCalls() const;
|
||||
std::map<int,Perform> getBranches() const;
|
||||
void setCall(Perform a);
|
||||
void setBranch(Perform a);
|
||||
void gcov_print() const;
|
||||
friend std::ostream &operator<<(std::ostream &out, const Gcov_info &a);
|
||||
};
|
||||
1570
Sapfor/_src/ExpressionTransform/control_flow_graph_part.cpp
Normal file
1570
Sapfor/_src/ExpressionTransform/control_flow_graph_part.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1350
Sapfor/_src/ExpressionTransform/expr_transform.cpp
Normal file
1350
Sapfor/_src/ExpressionTransform/expr_transform.cpp
Normal file
File diff suppressed because it is too large
Load Diff
128
Sapfor/_src/ExpressionTransform/expr_transform.h
Normal file
128
Sapfor/_src/ExpressionTransform/expr_transform.h
Normal file
@@ -0,0 +1,128 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include "dvm.h"
|
||||
#include "../Distribution/Distribution.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "../ParallelizationRegions/ParRegions.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
|
||||
#include "acc_analyzer.h"
|
||||
|
||||
|
||||
struct VariableItem;
|
||||
class VarsKeeper;
|
||||
class DataFlowItem;
|
||||
|
||||
SgExpression* ReplaceParameter_(SgExpression* e);
|
||||
SgExpression* ReplaceArrayBoundSizes(SgExpression *edim);
|
||||
SgExpression* ReplaceConstant(SgExpression *e);
|
||||
void getCoefsOfSubscript(std::pair<int, int> &retCoefs, SgExpression *exp, SgSymbol *doName);
|
||||
void createLinksToCopy(SgExpression* exOrig, SgExpression* exCopy);
|
||||
int CalculateInteger(SgExpression *expr, int &result);
|
||||
SgExpression* CalculateInteger(SgExpression *expr);
|
||||
void expressionAnalyzer(SgFile *file,
|
||||
const std::map<std::string, std::vector<DefUseList>> &defUseByFunctions,
|
||||
const std::map<std::string, CommonBlock*> &commonBlocks,
|
||||
const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo,
|
||||
const std::vector<ParallelRegion*> ®ions);
|
||||
|
||||
bool calculate(SgExpression *&exp);
|
||||
bool replaceConstantRec(SgExpression *&exp);
|
||||
|
||||
enum REPLACE_PTR_TYPE { SG_EXPRESSION, SG_STATEMENT };
|
||||
|
||||
void revertReplacements(const std::string &filename, bool back = false);
|
||||
|
||||
struct GraphItem {
|
||||
GraphItem(): CGraph(NULL), file_id(-1), calls(CallData()), commons(CommonData()), dldl(DoLoopDataList()), privateDone(false) {}
|
||||
int file_id;
|
||||
ControlFlowGraph* CGraph;
|
||||
CallData calls;
|
||||
CommonData commons;
|
||||
DoLoopDataList dldl;
|
||||
bool privateDone;
|
||||
~GraphItem() { if(CGraph) delete CGraph; }
|
||||
};
|
||||
|
||||
class GraphsKeeper {
|
||||
private:
|
||||
std::map<SgStatement*, GraphItem*> graphs;
|
||||
GraphsKeeper(): graphs(std::map<SgStatement*, GraphItem*>()) {}
|
||||
public:
|
||||
static GraphsKeeper* getGraphsKeeper();
|
||||
static void deleteGraphsKeeper();
|
||||
~GraphsKeeper()
|
||||
{
|
||||
for (auto &it : graphs)
|
||||
if (it.second)
|
||||
{
|
||||
delete it.second;
|
||||
it.second = NULL;
|
||||
}
|
||||
graphs.clear();
|
||||
}
|
||||
|
||||
GraphItem* buildGraph(SgStatement* st);
|
||||
GraphItem* getGraph(SgStatement *header);
|
||||
CBasicBlock* findBlock(SgStatement* stmt);
|
||||
};
|
||||
|
||||
struct FuncCallSE
|
||||
{
|
||||
std::string funcName;
|
||||
std::set<std::string> calls;
|
||||
FuncCallSE(std::string &n, std::set<std::string>& v) : funcName(n), calls(v) {}
|
||||
};
|
||||
|
||||
class CommonVarsOverseer
|
||||
{
|
||||
private:
|
||||
bool inited;
|
||||
|
||||
public:
|
||||
std::map<std::string, std::set<SgSymbol*>> funcKillsVars;
|
||||
CommonVarsOverseer() : inited(false), funcKillsVars(std::map<std::string, std::set<SgSymbol*>>()) {}
|
||||
bool isInited() { return inited; }
|
||||
void riseInited() { inited = true; }
|
||||
void addKilledVar(SgSymbol* symbol, const std::string &funcName)
|
||||
{
|
||||
auto founded = funcKillsVars.find(funcName);
|
||||
if (founded == funcKillsVars.end())
|
||||
funcKillsVars.insert(founded, std::make_pair(funcName, std::set<SgSymbol*>()))->second.insert(symbol);
|
||||
else
|
||||
founded->second.insert(symbol);
|
||||
}
|
||||
|
||||
std::set<SgSymbol*>* killedVars(const std::string &funcName)
|
||||
{
|
||||
auto founded = funcKillsVars.find(funcName);
|
||||
if (founded == funcKillsVars.end())
|
||||
return NULL;
|
||||
return &(founded->second);
|
||||
}
|
||||
};
|
||||
|
||||
std::map<SgStatement*, std::pair<std::set<SgStatement*>, std::set<SgStatement*>>> buildRequireReachMapForLoop(SgStatement *since, SgStatement *till, std::set<std::string> &privates);
|
||||
const std::map<SymbolKey, std::set<ExpressionValue*>> getReachingDefinitionsExt(SgStatement* stmt);
|
||||
void FillCFGInsAndOutsDefs(ControlFlowGraph*, std::map<SymbolKey, std::set<ExpressionValue*>> *inDefs, CommonVarsOverseer *overseer_Ptr);
|
||||
void CorrectInDefs(ControlFlowGraph*);
|
||||
void ClearCFGInsAndOutsDefs(ControlFlowGraph*);
|
||||
bool valueWithRecursion(const SymbolKey&, SgExpression*);
|
||||
bool valueWithFunctionCall(SgExpression*);
|
||||
bool valueWithArrayReference(SgExpression *exp, SgStatement* from);
|
||||
bool argIsReplaceable(int i, AnalysedCallsList* callData);
|
||||
bool argIsUsed(int i, AnalysedCallsList* callData);
|
||||
bool symbolInExpression(const SymbolKey &symbol, SgExpression *exp);
|
||||
void showDefs(std::map<SymbolKey, std::set<ExpressionValue>> *defs);
|
||||
void showDefs(std::map<SymbolKey, SgExpression*> *defs);
|
||||
void showDefsOfGraph(ControlFlowGraph *CGraph);
|
||||
void debugStructure(ControlFlowGraph *CGraph, const std::string &filename);
|
||||
bool findCFIsForStmt(SgStatement *st, std::vector <ControlFlowItem*> &cfis);
|
||||
std::map<SymbolKey, std::set<ExpressionValue*>> createHeaderInDefs(SgStatement *header);
|
||||
ControlFlowGraph* BuildUnfilteredReachingDefinitionsFor(SgStatement *header);
|
||||
void runPrivateAnalysis(SgStatement *main);
|
||||
SgStatement* findReplacedExpression(SgExpression* ex);
|
||||
2595
Sapfor/_src/GraphCall/graph_calls.cpp
Normal file
2595
Sapfor/_src/GraphCall/graph_calls.cpp
Normal file
File diff suppressed because it is too large
Load Diff
315
Sapfor/_src/GraphCall/graph_calls.h
Normal file
315
Sapfor/_src/GraphCall/graph_calls.h
Normal file
@@ -0,0 +1,315 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include "../Utils/AstWrapper.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../DirectiveProcessing/shadow.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
|
||||
static const char* paramNames[] =
|
||||
{ "NONE_T", "ARRAY_T", "STRING_ARRAY_T", "STRING_T", "SCALAR_CHAR_T", "SCALAR_BOOL_T", "SCALAR_SHORT_T", "SCALAR_INT_T", "SCALAR_LONG_INT_T",
|
||||
"SCALAR_FLOAT_T", "SCALAR_DOUBLE_T",
|
||||
"SCALAR_CMPLX_FLOAT_T", "SCALAR_CMPLX_DOUBLE_T", "EXTERNAL_T", "UNKNOWN_T" };
|
||||
|
||||
typedef enum parF { NONE_T, ARRAY_T, STRING_ARRAY_T, STRING_T, SCALAR_CHAR_T, SCALAR_BOOL_T, SCALAR_SHORT_T, SCALAR_INT_T, SCALAR_LONG_INT_T,
|
||||
SCALAR_FLOAT_T, SCALAR_DOUBLE_T,
|
||||
SCALAR_CMPLX_FLOAT_T, SCALAR_CMPLX_DOUBLE_T, EXTERNAL_T, UNKNOWN_T} paramType;
|
||||
|
||||
#ifndef IN_BIT
|
||||
#define IN_BIT 16
|
||||
#endif
|
||||
#ifndef OUT_BIT
|
||||
#define OUT_BIT 256
|
||||
#endif
|
||||
|
||||
struct FuncParam
|
||||
{
|
||||
FuncParam() { countOfPars = 0; }
|
||||
|
||||
void init(const int numPar)
|
||||
{
|
||||
countOfPars = numPar;
|
||||
if (numPar)
|
||||
{
|
||||
parameters.resize(numPar);
|
||||
parametersT.resize(numPar);
|
||||
inout_types.resize(numPar);
|
||||
std::fill(parametersT.begin(), parametersT.end(), NONE_T);
|
||||
std::fill(inout_types.begin(), inout_types.end(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void completeParams()
|
||||
{
|
||||
for (int z = 0; z < countOfPars; ++z)
|
||||
if (inout_types[z] == 0)
|
||||
inout_types[z] = IN_BIT;
|
||||
}
|
||||
|
||||
bool isArgIn(const int num) const
|
||||
{
|
||||
if (num >= countOfPars)
|
||||
return false;
|
||||
else
|
||||
return (inout_types[num] & IN_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isArgOut(const int num) const
|
||||
{
|
||||
if (num >= countOfPars)
|
||||
return false;
|
||||
else
|
||||
return (inout_types[num] & OUT_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isArgInOut(const int num) const
|
||||
{
|
||||
if (num >= countOfPars)
|
||||
return false;
|
||||
else
|
||||
return isArgIn(num) && isArgOut(num);
|
||||
}
|
||||
|
||||
static bool isArgIn(int64_t type) { return (type & IN_BIT) != 0; }
|
||||
static bool isArgOut(int64_t type) { return (type & OUT_BIT) != 0; }
|
||||
static bool isArgInOut(int64_t type) { return isArgIn(type) && isArgOut(type); }
|
||||
|
||||
std::vector<std::string> identificators;
|
||||
std::vector<void*> parameters;
|
||||
std::vector<paramType> parametersT;
|
||||
std::vector<int> inout_types;
|
||||
int countOfPars;
|
||||
};
|
||||
|
||||
#ifndef IN_BIT
|
||||
#undef IN_BIT
|
||||
#endif
|
||||
#ifndef OUT_BIT
|
||||
#undef OUT_BIT
|
||||
#endif
|
||||
|
||||
struct NestedFuncCall
|
||||
{
|
||||
std::string CalledFuncName;
|
||||
std::vector<std::vector<int>> NoOfParamUsedForCall;
|
||||
|
||||
NestedFuncCall(std::string funcName) : CalledFuncName(funcName) { }
|
||||
|
||||
NestedFuncCall(std::string funcName, int ParsNum) :
|
||||
CalledFuncName(funcName),
|
||||
NoOfParamUsedForCall(std::vector<std::vector<int>>(ParsNum))
|
||||
{ }
|
||||
};
|
||||
|
||||
struct FuncInfoCallFrom {
|
||||
// <name, line>
|
||||
std::pair<std::string, int> detailCallsFrom;
|
||||
// <pointer, SG_VAR> SgStatement for PROC_STAT, SgExpression for FUNC_CALL, VAR_REF for external calls
|
||||
std::pair<void*, int> pointerDetailCallsFrom;
|
||||
// parent SgStatement* of FUNC_CALL
|
||||
void* parentForPointer;
|
||||
FuncParam actualParams;
|
||||
};
|
||||
|
||||
struct FuncInfo
|
||||
{
|
||||
std::string funcName;
|
||||
std::pair<int, int> linesNum;
|
||||
std::string fileName;
|
||||
Statement *funcPointer;
|
||||
bool isMain;
|
||||
bool isInterface;
|
||||
|
||||
std::set<std::string> callsFrom; //calls from this function
|
||||
std::set<FuncInfo*> callsFromV;
|
||||
std::vector<FuncInfoCallFrom> callsFromDetailed;
|
||||
|
||||
std::map<std::string, std::set<std::string>> commonBlocks;
|
||||
|
||||
std::vector<FuncInfo*> callsTo; //calls of this function
|
||||
FuncParam funcParams;
|
||||
std::vector<bool> isParamUsedAsIndex;
|
||||
std::vector<NestedFuncCall> funcsCalledFromThis; // size = amount of calls in this func;
|
||||
// if (FuncsCalledFromThis[func_call_idx].
|
||||
// NoOfParamUsedForCall.size() == 0) - no params of cur func used
|
||||
|
||||
ShadowNode* shadowTreeStart;
|
||||
ShadowNode* shadowTreeEnd;
|
||||
std::map<void*, ShadowNode*> allShadowNodes;
|
||||
std::set<DIST::Array*> allUsedArrays; // real array refs
|
||||
std::set<DIST::Array*> usedArraysWrite; // real array refs
|
||||
|
||||
std::vector<LoopGraph*> loopsInFunc;
|
||||
|
||||
std::set<int> linesOfIO;
|
||||
std::set<int> linesOfStop;
|
||||
|
||||
std::map<std::string, FuncInfo*> interfaceBlocks;
|
||||
std::map<std::string, FuncInfo*> interfaceSynonims;
|
||||
|
||||
std::vector<FuncInfo*> entry; // all entry points
|
||||
|
||||
std::set<std::string> externalCalls;
|
||||
|
||||
bool isPure; // does this func or funcs called from this have common block[s] and have no side effects
|
||||
bool doNotInline;
|
||||
bool doNotAnalyze;
|
||||
bool needToInline;
|
||||
bool deadFunction;
|
||||
|
||||
// for RESOLVE_PAR_REGIONS
|
||||
int inRegion; // 0 - none, 1 - explicit, 2 - implicit, 3 - indirect
|
||||
std::set<uint64_t> callRegions; // 0 - default; forall i > 0, i - user region
|
||||
bool isInRegion() { return inRegion == 1 || inRegion == 2; }
|
||||
bool isIndirect() { return inRegion == 3; }
|
||||
//
|
||||
|
||||
std::vector<FuncInfo*> fullCopiesOfThisFunction;
|
||||
|
||||
FuncInfo() :
|
||||
doNotInline(false), funcPointer(NULL), doNotAnalyze(false), needToInline(false),
|
||||
deadFunction(false), inRegion(0), isPure(false), isMain(false), shadowTreeStart(NULL), shadowTreeEnd(NULL),
|
||||
isInterface(false) { }
|
||||
|
||||
FuncInfo(const std::string &funcName, const std::pair<int, int> &lineNum) :
|
||||
funcName(funcName), linesNum(lineNum), doNotInline(false), funcPointer(NULL),
|
||||
doNotAnalyze(false), needToInline(false), deadFunction(false), inRegion(0), isMain(false),
|
||||
isPure(false), shadowTreeStart(NULL), shadowTreeEnd(NULL), isInterface(false) { }
|
||||
|
||||
#if !__SPC
|
||||
FuncInfo(const std::string &funcName, const std::pair<int, int> &lineNum, Statement *pointer) :
|
||||
funcName(funcName), linesNum(lineNum), doNotInline(false), funcPointer(pointer),
|
||||
doNotAnalyze(false), needToInline(false), deadFunction(false), inRegion(0), isMain(false),
|
||||
isPure(false), shadowTreeStart(NULL), shadowTreeEnd(NULL), isInterface(false) { fileName = pointer->fileName(); }
|
||||
#endif
|
||||
|
||||
std::vector<std::pair<void*, int>> GetDetailedCallInfo(const std::string &funcName)
|
||||
{
|
||||
std::vector<std::pair<void*, int>> result;
|
||||
for (int i = 0; i < callsFromDetailed.size(); ++i)
|
||||
{
|
||||
if (callsFromDetailed[i].detailCallsFrom.first == funcName)
|
||||
result.push_back(callsFromDetailed[i].pointerDetailCallsFrom);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string getFuncNameWithContainsByRegion(const uint64_t regionId)
|
||||
{
|
||||
if (regionId && callRegions.size() > 1 && callRegions.find(regionId) != callRegions.end())
|
||||
return funcName + "_r" + std::to_string(regionId);
|
||||
return funcName;
|
||||
}
|
||||
|
||||
std::string getFuncNameByRegion(const std::string &shortName, const uint64_t regionId)
|
||||
{
|
||||
if (regionId && callRegions.size() > 1 && callRegions.find(regionId) != callRegions.end())
|
||||
return shortName + "_r" + std::to_string(regionId);
|
||||
return shortName;
|
||||
}
|
||||
|
||||
void removeNonDistrArrays()
|
||||
{
|
||||
std::set<DIST::Array*> newUsedArrays;
|
||||
for (auto &elem : allUsedArrays)
|
||||
if (elem->GetDistributeFlagVal() == DIST::DISTR)
|
||||
newUsedArrays.insert(elem);
|
||||
allUsedArrays = newUsedArrays;
|
||||
}
|
||||
|
||||
bool usesIO() const { return (linesOfIO.size() != 0 || linesOfStop.size() != 0); }
|
||||
|
||||
std::string getCallName(const std::pair<void*, int>& call_info, const std::string& name, int line)
|
||||
{
|
||||
if (line <= 0)
|
||||
return name;
|
||||
|
||||
std::set<std::string> names;
|
||||
|
||||
for (auto& call : callsFromDetailed)
|
||||
{
|
||||
if (call.pointerDetailCallsFrom == call_info && call.detailCallsFrom.second == line)
|
||||
return call.detailCallsFrom.first;
|
||||
|
||||
if (call.detailCallsFrom.second == line)
|
||||
if (call.detailCallsFrom.first.find(name) != std::string::npos)
|
||||
names.insert(call.detailCallsFrom.first);
|
||||
}
|
||||
|
||||
//TODO: detect func call better
|
||||
if (names.size() == 1)
|
||||
return *names.begin();
|
||||
|
||||
//try to find in next lvl calls
|
||||
for (auto& call : callsFromDetailed)
|
||||
{
|
||||
if (call.detailCallsFrom.second == line)
|
||||
{
|
||||
std::string name_next = call.detailCallsFrom.first;
|
||||
std::set<FuncInfo*> next, done;
|
||||
|
||||
for (auto& callFrom : callsFromV)
|
||||
if (callFrom->funcName == name_next)
|
||||
next.insert(callFrom);
|
||||
|
||||
done = next;
|
||||
while (next.size())
|
||||
{
|
||||
auto curr = next;
|
||||
next.clear();
|
||||
|
||||
for (auto& callFrom : curr)
|
||||
{
|
||||
for (auto& call : callFrom->callsFromDetailed)
|
||||
{
|
||||
if (call.detailCallsFrom.first == name)
|
||||
return call.detailCallsFrom.first;
|
||||
}
|
||||
|
||||
for (auto& callFromNext : callFrom->callsFromV)
|
||||
{
|
||||
if (done.find(callFromNext) == done.end())
|
||||
{
|
||||
next.insert(callFromNext);
|
||||
done.insert(callFromNext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
struct CallV
|
||||
{
|
||||
std::string fName;
|
||||
std::string fileName;
|
||||
bool isMain;
|
||||
int inRegion;
|
||||
|
||||
CallV() : inRegion(0), isMain(false) { }
|
||||
|
||||
CallV(const std::string &fName) :
|
||||
fName(fName), fileName(""), isMain(false), inRegion(0)
|
||||
{ }
|
||||
|
||||
CallV(const std::string &fName, const std::string &fileName, bool isMain) :
|
||||
fName(fName), fileName(fileName), isMain(isMain), inRegion(0)
|
||||
{ }
|
||||
|
||||
std::string to_string()
|
||||
{
|
||||
return fName + "@" + fileName + "@" + (isMain ? "1" : "0") + "@" + std::to_string(inRegion);
|
||||
}
|
||||
};
|
||||
|
||||
void propagateArrayFlags(const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays, std::map<std::string, std::vector<Messages>> &SPF_messages);
|
||||
void removeDistrStateFromDeadFunctions(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays);
|
||||
bool detectMpiCalls(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, std::map<std::string, std::vector<Messages>>& SPF_messages);
|
||||
int getLvlCall(FuncInfo* currF, int lvl, const std::string& func, const std::string& file, int line);
|
||||
void compliteArrayUsage(DIST::Arrays<int>& allArraysForRegion, std::map<std::tuple<int, std::string, std::string>, DIST::Array*>& createdArrays, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, const std::map<DIST::Array*, std::tuple<int, std::string, std::string>>& tableOfUniqNamesByArray);
|
||||
void remoteNotUsedArrays(std::map<std::tuple<int, std::string, std::string>, DIST::Array*>& createdArrays, const std::set<DIST::Array*>& usedArraysAcrossRegions, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
981
Sapfor/_src/GraphCall/graph_calls_base.cpp
Normal file
981
Sapfor/_src/GraphCall/graph_calls_base.cpp
Normal file
@@ -0,0 +1,981 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "../Utils/errors.h"
|
||||
#include "graph_calls.h"
|
||||
#include "../Distribution/Distribution.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../ParallelizationRegions/ParRegions.h"
|
||||
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::set;
|
||||
using std::to_string;
|
||||
using std::tuple;
|
||||
using std::pair;
|
||||
|
||||
#define DEB 0
|
||||
void createMapOfFunc(const vector<FuncInfo*> &allFuncInfo, map<pair<string, int>, FuncInfo*> &mapFuncInfo)
|
||||
{
|
||||
for (auto &func : allFuncInfo)
|
||||
mapFuncInfo[make_pair(func->fileName, func->linesNum.first)] = func;
|
||||
}
|
||||
|
||||
void createMapOfFunc(const vector<FuncInfo*> &allFuncInfo, map<string, FuncInfo*> &mapFuncInfo)
|
||||
{
|
||||
for (auto &func : allFuncInfo)
|
||||
mapFuncInfo[func->funcName] = func;
|
||||
}
|
||||
|
||||
void createMapOfFunc(const map<string, vector<FuncInfo*>> &allFuncInfo, map<string, FuncInfo*> &mapFuncInfo)
|
||||
{
|
||||
for (auto it = allFuncInfo.begin(); it != allFuncInfo.end(); ++it)
|
||||
for (int k = 0; k < it->second.size(); ++k)
|
||||
mapFuncInfo[it->second[k]->funcName] = it->second[k];
|
||||
}
|
||||
|
||||
FuncInfo* getFuncInfo(const map<string, FuncInfo*> &funcMap, const string &funcName)
|
||||
{
|
||||
auto it = funcMap.find(funcName);
|
||||
if (it == funcMap.end())
|
||||
return NULL;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
string removeString(const string &toRemove, const string &inStr)
|
||||
{
|
||||
string outStr(inStr);
|
||||
const size_t found = outStr.find(toRemove);
|
||||
if (found != string::npos)
|
||||
outStr.erase(found, toRemove.length());
|
||||
return outStr;
|
||||
}
|
||||
|
||||
void updateFuncInfo(const map<string, vector<FuncInfo*>> &allFuncInfo) // const here
|
||||
{
|
||||
bool changesDone = false;
|
||||
map<string, FuncInfo*> mapFuncInfo;
|
||||
createMapOfFunc(allFuncInfo, mapFuncInfo);
|
||||
|
||||
do
|
||||
{
|
||||
changesDone = false;
|
||||
for (auto &it : mapFuncInfo)
|
||||
{
|
||||
FuncInfo *currInfo = it.second;
|
||||
|
||||
for(auto &funcCall : currInfo->funcsCalledFromThis)
|
||||
{
|
||||
// Find pointer to info of called function
|
||||
auto itCalledFunc = mapFuncInfo.find(funcCall.CalledFuncName);
|
||||
|
||||
if (itCalledFunc != mapFuncInfo.end() && !itCalledFunc->second->isInterface)
|
||||
{
|
||||
FuncInfo *calledFunc = itCalledFunc->second;
|
||||
|
||||
// check for pureness
|
||||
if (!calledFunc->isPure && currInfo->isPure)
|
||||
{
|
||||
currInfo->isPure = false;
|
||||
changesDone = true;
|
||||
}
|
||||
|
||||
// check for using parameter as index
|
||||
// Iterate through all pars of the call
|
||||
for (int parNo = 0; parNo < funcCall.NoOfParamUsedForCall.size(); ++parNo)
|
||||
{
|
||||
auto& parOfCalled = funcCall.NoOfParamUsedForCall[parNo];
|
||||
// If this par of called func is used as index change
|
||||
if (calledFunc->isParamUsedAsIndex[parNo])
|
||||
{
|
||||
// Then pars of calling func which are used in this par of called
|
||||
// are also used as index
|
||||
for (auto &parOfCalling : parOfCalled)
|
||||
{
|
||||
if (!currInfo->isParamUsedAsIndex[parOfCalling])
|
||||
{
|
||||
changesDone = true;
|
||||
currInfo->isParamUsedAsIndex[parOfCalling] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// propagate inout types
|
||||
for (int parNo = 0; parNo < funcCall.NoOfParamUsedForCall.size(); ++parNo)
|
||||
{
|
||||
auto& parOfCalled = funcCall.NoOfParamUsedForCall[parNo];
|
||||
if (parOfCalled.size() == 0)
|
||||
continue;
|
||||
|
||||
if (calledFunc->funcParams.isArgOut(parNo))
|
||||
{
|
||||
for (auto& num : parOfCalled)
|
||||
{
|
||||
if (!currInfo->funcParams.isArgOut(num))
|
||||
{
|
||||
currInfo->funcParams.inout_types[num] |= OUT_BIT;
|
||||
changesDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (calledFunc->funcParams.isArgIn(parNo))
|
||||
{
|
||||
for (auto& num : parOfCalled)
|
||||
{
|
||||
if (!currInfo->funcParams.isArgIn(num))
|
||||
{
|
||||
currInfo->funcParams.inout_types[num] |= IN_BIT;
|
||||
changesDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (changesDone);
|
||||
|
||||
// check for io usage
|
||||
do
|
||||
{
|
||||
changesDone = false;
|
||||
for (auto &it : mapFuncInfo)
|
||||
{
|
||||
FuncInfo *currInfo = it.second;
|
||||
for (auto &callInfo : currInfo->callsFromDetailed)
|
||||
{
|
||||
auto& funcCall = callInfo.detailCallsFrom;
|
||||
auto itCalledFunc = mapFuncInfo.find(funcCall.first);
|
||||
if (itCalledFunc != mapFuncInfo.end())
|
||||
{
|
||||
FuncInfo *calledFunc = itCalledFunc->second;
|
||||
if (calledFunc->linesOfIO.size())
|
||||
{
|
||||
const int lineOfCall = funcCall.second;
|
||||
auto it = currInfo->linesOfIO.find(lineOfCall);
|
||||
if (it == currInfo->linesOfIO.end())
|
||||
{
|
||||
currInfo->linesOfIO.insert(lineOfCall);
|
||||
changesDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (changesDone);
|
||||
|
||||
//fill all pars IN, if they have NONE status
|
||||
for (auto& it : mapFuncInfo)
|
||||
{
|
||||
FuncInfo* currInfo = it.second;
|
||||
currInfo->funcParams.completeParams();
|
||||
}
|
||||
}
|
||||
|
||||
int CreateCallGraphViz(const char *fileName, const map<string, vector<FuncInfo*>> &funcByFile, map<string, CallV> &V, vector<string> &E)
|
||||
{
|
||||
map<string, FuncInfo*> allFuncs;
|
||||
createMapOfFunc(funcByFile, allFuncs);
|
||||
|
||||
string graph = "";
|
||||
graph += "digraph G{\n";
|
||||
|
||||
auto it = funcByFile.begin();
|
||||
int fileNum = 0;
|
||||
set<string> inCluster;
|
||||
set<string> unknownCluster;
|
||||
|
||||
char buf[1024];
|
||||
while (it != funcByFile.end())
|
||||
{
|
||||
sprintf(buf, "subgraph cluster%d {\n", fileNum);
|
||||
graph += buf;
|
||||
|
||||
const int dimSize = (int)it->second.size();
|
||||
set<string> uniqNames;
|
||||
for (int k = 0; k < dimSize; ++k)
|
||||
{
|
||||
const string currfunc = it->second[k]->funcName;
|
||||
auto it = uniqNames.find(currfunc);
|
||||
if (it == uniqNames.end())
|
||||
{
|
||||
uniqNames.insert(it, currfunc);
|
||||
inCluster.insert(currfunc);
|
||||
sprintf(buf, "\"%s\"\n", currfunc.c_str());
|
||||
graph += buf;
|
||||
}
|
||||
}
|
||||
sprintf(buf, "label = \"file <%s>\"\n", removeString(".\\", it->first).c_str());
|
||||
graph += buf;
|
||||
graph += "}\n";
|
||||
|
||||
fileNum++;
|
||||
it++;
|
||||
}
|
||||
|
||||
it = funcByFile.begin();
|
||||
while (it != funcByFile.end())
|
||||
{
|
||||
const char *formatString = "\"%s\" -> \"%s\" [minlen=2.0];\n";
|
||||
const int dimSize = (int)it->second.size();
|
||||
for (int k = 0; k < dimSize; ++k)
|
||||
{
|
||||
const string &callFrom = it->second[k]->funcName;
|
||||
const FuncInfo *callFromP = it->second[k];
|
||||
|
||||
for (auto &callItem : it->second[k]->callsFrom)
|
||||
{
|
||||
sprintf(buf, formatString, callFrom.c_str(), callItem.c_str());
|
||||
graph += buf;
|
||||
|
||||
if (inCluster.find(callFrom) == inCluster.end())
|
||||
unknownCluster.insert(callFrom);
|
||||
if (inCluster.find(callItem) == inCluster.end())
|
||||
unknownCluster.insert(callItem);
|
||||
|
||||
if (V.find(callFrom) == V.end())
|
||||
{
|
||||
V[callFrom] = CallV(callFromP->funcName, callFromP->fileName, callFromP->isMain);
|
||||
V[callFrom].inRegion = callFromP->inRegion;
|
||||
}
|
||||
|
||||
if (V.find(callItem) == V.end())
|
||||
{
|
||||
auto it = allFuncs.find(callItem);
|
||||
if (it == allFuncs.end())
|
||||
V[callItem] = CallV(callItem);
|
||||
else
|
||||
{
|
||||
auto currF = it->second;
|
||||
V[callItem] = CallV(callItem, currF->fileName, currF->isMain);
|
||||
V[callItem].inRegion = currF->inRegion;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
E.push_back(callFrom);
|
||||
E.push_back(callItem);
|
||||
}
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
if (unknownCluster.size() > 0)
|
||||
{
|
||||
sprintf(buf, "subgraph cluster%d {\n", fileNum);
|
||||
graph += buf;
|
||||
|
||||
for (auto &func : unknownCluster)
|
||||
{
|
||||
sprintf(buf, "\"%s\"\n", func.c_str());
|
||||
graph += buf;
|
||||
}
|
||||
sprintf(buf, "label = \"file <UNKNOWN>\"\n");
|
||||
graph += buf;
|
||||
graph += "}\n";
|
||||
}
|
||||
|
||||
graph += "overlap=false\n";
|
||||
graph += "}\n";
|
||||
|
||||
if (fileName)
|
||||
{
|
||||
FILE *out = fopen(fileName, "w");
|
||||
if (out == NULL)
|
||||
{
|
||||
__spf_print(1, "can not open file %s\n", fileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(out, graph.c_str());
|
||||
fclose(out);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CreateFuncInfo(const char *fileName, const map<string, vector<FuncInfo*>> &funcByFile)
|
||||
{
|
||||
string funcOut = "";
|
||||
for (auto &byFile : funcByFile)
|
||||
{
|
||||
funcOut += "FILE " + byFile.first + ":\n";
|
||||
for (auto &func : byFile.second)
|
||||
{
|
||||
funcOut += (func->isInterface ? ("INTERFACE OF ") : "") + string(" FUNCTION '") +
|
||||
func->funcName + "' " + (func->isPure ? " is PURE" : "is IMPURE") + "\n";
|
||||
char buf[256];
|
||||
sprintf(buf, " LINES [%d, %d] \n", func->linesNum.first, func->linesNum.second);
|
||||
funcOut += buf;
|
||||
sprintf(buf, " PARAMETERS %d:\n", func->funcParams.countOfPars);
|
||||
funcOut += buf;
|
||||
for (int z = 0; z < func->funcParams.countOfPars; ++z)
|
||||
{
|
||||
bool in = func->funcParams.isArgIn(z);
|
||||
bool out = func->funcParams.isArgOut(z);
|
||||
const char *inout = "";
|
||||
if (in && out)
|
||||
inout = "IN/OUT";
|
||||
else if (in)
|
||||
inout = "IN";
|
||||
else if (out)
|
||||
inout = "OUT";
|
||||
|
||||
sprintf(buf, " %s: type '%s', %s\n", func->funcParams.identificators[z].c_str(),
|
||||
paramNames[func->funcParams.parametersT[z]],
|
||||
inout);
|
||||
funcOut += buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fileName)
|
||||
{
|
||||
FILE *out = fopen(fileName, "w");
|
||||
if (out == NULL)
|
||||
{
|
||||
__spf_print(1, "can not open file %s\n", fileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(out, funcOut.c_str());
|
||||
fclose(out);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern map<string, vector<FuncInfo*>> allFuncInfo; // file -> Info
|
||||
FuncInfo* isUserFunctionInProject(const string &func)
|
||||
{
|
||||
FuncInfo *ret = NULL;
|
||||
for (auto &it : allFuncInfo)
|
||||
{
|
||||
for (auto &currF : it.second)
|
||||
{
|
||||
if (currF->funcName == func)
|
||||
{
|
||||
ret = currF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
string convertToString(const FuncInfo *currFunc)
|
||||
{
|
||||
string result = "";
|
||||
if (currFunc)
|
||||
{
|
||||
result += "|" + currFunc->funcName + "|" + to_string(currFunc->linesNum.first) +
|
||||
"#" + to_string(currFunc->linesNum.second) +
|
||||
"#" + to_string(currFunc->callsFromDetailed.size()) +
|
||||
"#" + to_string(currFunc->needToInline) + "#" + to_string(currFunc->doNotInline) +
|
||||
"#" + to_string(currFunc->doNotAnalyze) + "#" + to_string((int)currFunc->isMain);
|
||||
|
||||
result += "#" + to_string(currFunc->funcParams.countOfPars);
|
||||
if (currFunc->funcParams.countOfPars)
|
||||
{
|
||||
for (int z = 0; z < currFunc->funcParams.countOfPars; ++z)
|
||||
{
|
||||
result += "#" + currFunc->funcParams.identificators[z] + "#" + to_string(currFunc->funcParams.inout_types[z]);
|
||||
result += "#" + string(paramNames[currFunc->funcParams.parametersT[z]]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < currFunc->callsFromDetailed.size(); ++i)
|
||||
result += "|" + currFunc->callsFromDetailed[i].detailCallsFrom.first + "|" + to_string(currFunc->callsFromDetailed[i].detailCallsFrom.second);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Find dead functions and fill callTo / callFrom information
|
||||
void findDeadFunctionsAndFillCalls(map<string, vector<FuncInfo*>> &allFuncInfo, map<string, vector<Messages>> &allMessages, bool noPrint)
|
||||
{
|
||||
map<string, FuncInfo*> mapFuncInfo;
|
||||
createMapOfFunc(allFuncInfo, mapFuncInfo);
|
||||
|
||||
set<string> allExternalCalls;
|
||||
set<string> allChildCalls;
|
||||
|
||||
for (auto &it : mapFuncInfo)
|
||||
{
|
||||
FuncInfo *currInfo = it.second;
|
||||
allChildCalls.insert(currInfo->callsFrom.begin(), currInfo->callsFrom.end());
|
||||
allExternalCalls.insert(currInfo->externalCalls.begin(), currInfo->externalCalls.end());
|
||||
}
|
||||
|
||||
for (auto &it : mapFuncInfo)
|
||||
{
|
||||
FuncInfo *currInfo = it.second;
|
||||
if (allChildCalls.find(it.first) == allChildCalls.end())
|
||||
if (!currInfo->isMain && allExternalCalls.find(currInfo->funcName) == allExternalCalls.end())
|
||||
currInfo->deadFunction = currInfo->doNotAnalyze = true;
|
||||
}
|
||||
|
||||
if (!noPrint)
|
||||
{
|
||||
for (auto &it : allFuncInfo)
|
||||
{
|
||||
const string &currF = it.first;
|
||||
auto itM = allMessages.find(currF);
|
||||
if (itM == allMessages.end())
|
||||
itM = allMessages.insert(itM, make_pair(currF, vector<Messages>()));
|
||||
|
||||
for (auto& func : it.second)
|
||||
if (func->deadFunction)
|
||||
itM->second.push_back(Messages(WARR, func->linesNum.first, R47, L"This function is not called in current project", 1015));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &it : mapFuncInfo)
|
||||
{
|
||||
FuncInfo *currInfo = it.second;
|
||||
for (auto &k : currInfo->callsFrom)
|
||||
{
|
||||
auto itFound = mapFuncInfo.find(k);
|
||||
if (itFound != mapFuncInfo.end())
|
||||
{
|
||||
FuncInfo *callFrom = itFound->second;
|
||||
callFrom->callsTo.push_back(currInfo);
|
||||
currInfo->callsFromV.insert(callFrom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FuncInfo* main = NULL;
|
||||
for (auto& it : mapFuncInfo)
|
||||
if (it.second->isMain)
|
||||
main = it.second;
|
||||
|
||||
checkNull(main, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
set<FuncInfo*> liveFunctions;
|
||||
liveFunctions.insert(main);
|
||||
for (auto& callFrom : main->callsFromV)
|
||||
liveFunctions.insert(callFrom);
|
||||
|
||||
//find live functions
|
||||
bool changes = true;
|
||||
while (changes)
|
||||
{
|
||||
changes = false;
|
||||
for (auto& currInfo : liveFunctions)
|
||||
{
|
||||
for (auto& callFrom : currInfo->callsFromV) {
|
||||
if (liveFunctions.find(callFrom) == liveFunctions.end()) {
|
||||
changes = true;
|
||||
liveFunctions.insert(callFrom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// propagate 'deadFunction' status for all 'CallsFrom' from dead functions
|
||||
changes = true;
|
||||
while (changes)
|
||||
{
|
||||
changes = false;
|
||||
|
||||
for (auto& it : mapFuncInfo)
|
||||
{
|
||||
FuncInfo* currInfo = it.second;
|
||||
if (currInfo->deadFunction == false)
|
||||
continue;
|
||||
|
||||
for (auto& callFrom : currInfo->callsFrom)
|
||||
{
|
||||
auto itFrom = mapFuncInfo.find(callFrom);
|
||||
if (itFrom != mapFuncInfo.end())
|
||||
{
|
||||
auto func = itFrom->second;
|
||||
if (!func->deadFunction && liveFunctions.find(func) == liveFunctions.end())
|
||||
{
|
||||
changes = true;
|
||||
func->deadFunction = func->doNotAnalyze = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addLinks(const FuncParam &actual, const FuncParam &formal, map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
|
||||
{
|
||||
if (actual.parameters.size() != formal.parameters.size())
|
||||
return;
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < actual.parameters.size(); ++i)
|
||||
if (actual.parametersT[i] == formal.parametersT[i] && formal.parametersT[i] == ARRAY_T)
|
||||
{
|
||||
//printf("add lhs %s -> rhs %s\n", ((DIST::Array*)formal.parameters[i])->GetName().c_str(), ((DIST::Array*)actual.parameters[i])->GetName().c_str());
|
||||
if (((DIST::Array*)formal.parameters[i]) == ((DIST::Array*)actual.parameters[i]))
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
arrayLinksByFuncCalls[(DIST::Array*)formal.parameters[i]].insert((DIST::Array*)actual.parameters[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool propagateUp(DIST::Array *from, set<DIST::Array*> to, DIST::distFlag flag, bool &change, map<string, vector<Messages>> &SPF_messages)
|
||||
{
|
||||
bool globalChange = false;
|
||||
if (from->GetDistributeFlagVal() == flag)
|
||||
{
|
||||
for (auto &realRef : to)
|
||||
{
|
||||
auto val = realRef->GetDistributeFlagVal();
|
||||
if (val != flag)
|
||||
{
|
||||
//exclude this case
|
||||
if (flag == DIST::IO_PRIV && val == DIST::SPF_PRIV ||
|
||||
flag == DIST::NO_DISTR && val == DIST::SPF_PRIV ||
|
||||
flag == DIST::NO_DISTR && val == DIST::IO_PRIV)
|
||||
;
|
||||
else
|
||||
{
|
||||
realRef->SetDistributeFlag(flag);
|
||||
if (flag == DIST::IO_PRIV)
|
||||
{
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of DVM's I/O constraints", to_wstring(realRef->GetShortName()).c_str());
|
||||
__spf_printToLongBuf(messageR, R68, to_wstring(realRef->GetShortName()).c_str());
|
||||
|
||||
auto places = realRef->GetDeclInfo();
|
||||
for (auto& place : places)
|
||||
getObjectForFileFromMap(place.first.c_str(), SPF_messages).push_back(Messages(WARR, place.second, messageR, messageE, 1037));
|
||||
}
|
||||
#if DEB
|
||||
printf("up: set %d %s\n", flag, realRef->GetName().c_str());
|
||||
#endif
|
||||
change = true;
|
||||
globalChange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return globalChange;
|
||||
}
|
||||
|
||||
static bool propagateFlag(bool isDown, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
|
||||
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
|
||||
map<string, vector<Messages>> &SPF_messages)
|
||||
{
|
||||
bool globalChange = false;
|
||||
bool change = true;
|
||||
while (change)
|
||||
{
|
||||
change = false;
|
||||
for (auto &array : declaredArrays)
|
||||
{
|
||||
set<DIST::Array*> realArrayRefs;
|
||||
getRealArrayRefs(array.second.first, array.second.first, realArrayRefs, arrayLinksByFuncCalls);
|
||||
|
||||
bool allNonDistr = true;
|
||||
bool allDistr = true;
|
||||
bool nonDistrSpfPriv = false;
|
||||
bool nonDistrIOPriv = false;
|
||||
bool init = false;
|
||||
|
||||
// propagate SPF to down calls
|
||||
for (auto &realRef : realArrayRefs)
|
||||
{
|
||||
if (realRef != array.second.first)
|
||||
{
|
||||
bool nonDistr = realRef->IsNotDistribute();
|
||||
if (realRef->GetDistributeFlagVal() == DIST::SPF_PRIV)
|
||||
nonDistrSpfPriv = true;
|
||||
else if (realRef->GetDistributeFlagVal() == DIST::IO_PRIV)
|
||||
nonDistrIOPriv = true;
|
||||
|
||||
allNonDistr = allNonDistr && nonDistr;
|
||||
allDistr = allDistr && !nonDistr;
|
||||
init = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (init)
|
||||
{
|
||||
if (allNonDistr && array.second.first->IsNotDistribute() == false)
|
||||
{
|
||||
if (isDown)
|
||||
{
|
||||
if (nonDistrSpfPriv)
|
||||
{
|
||||
array.second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
if (DEB)
|
||||
printf("down: set %d %s\n", DIST::SPF_PRIV, array.second.first->GetName().c_str());
|
||||
}
|
||||
else if (nonDistrIOPriv)
|
||||
{
|
||||
array.second.first->SetDistributeFlag(DIST::IO_PRIV);
|
||||
if (DEB)
|
||||
printf("down: set %d %s\n", DIST::IO_PRIV, array.second.first->GetName().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
array.second.first->SetDistributeFlag(DIST::NO_DISTR);
|
||||
if (DEB)
|
||||
printf("down: set %d %s\n", DIST::NO_DISTR, array.second.first->GetName().c_str());
|
||||
}
|
||||
change = true;
|
||||
globalChange = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isDown)
|
||||
{
|
||||
bool ret = propagateUp(array.second.first, realArrayRefs, DIST::SPF_PRIV, change, SPF_messages);
|
||||
globalChange = globalChange || ret;
|
||||
ret = propagateUp(array.second.first, realArrayRefs, DIST::IO_PRIV, change, SPF_messages);
|
||||
globalChange = globalChange || ret;
|
||||
ret = propagateUp(array.second.first, realArrayRefs, DIST::NO_DISTR, change, SPF_messages);
|
||||
globalChange = globalChange || ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return globalChange;
|
||||
}
|
||||
|
||||
void propagateArrayFlags(const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
|
||||
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
|
||||
map<string, vector<Messages>> &SPF_messages)
|
||||
{
|
||||
bool change = true;
|
||||
while (change)
|
||||
{
|
||||
bool changeD = propagateFlag(true, arrayLinksByFuncCalls, declaredArrays, SPF_messages);
|
||||
bool changeU = propagateFlag(false, arrayLinksByFuncCalls, declaredArrays, SPF_messages);
|
||||
|
||||
change = changeD || changeU;
|
||||
}
|
||||
}
|
||||
|
||||
static void aggregateUsedArrays(map<string, FuncInfo*> &funcByName, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
|
||||
{
|
||||
//change to real refs
|
||||
for (auto &func : funcByName)
|
||||
{
|
||||
{
|
||||
set<DIST::Array*> curr = func.second->allUsedArrays;
|
||||
set<DIST::Array*> newRefs;
|
||||
for (auto &array : curr)
|
||||
getRealArrayRefs(array, array, newRefs, arrayLinksByFuncCalls);
|
||||
func.second->allUsedArrays.clear();
|
||||
for (auto &newArray : newRefs)
|
||||
if (newArray->IsNotDistribute() == false)
|
||||
func.second->allUsedArrays.insert(newArray);
|
||||
}
|
||||
|
||||
{
|
||||
set<DIST::Array*> curr = func.second->usedArraysWrite;
|
||||
set<DIST::Array*> newRefs;
|
||||
for (auto &array : curr)
|
||||
getRealArrayRefs(array, array, newRefs, arrayLinksByFuncCalls);
|
||||
func.second->usedArraysWrite.clear();
|
||||
for (auto &newArray : newRefs)
|
||||
if (newArray->IsNotDistribute() == false)
|
||||
func.second->usedArraysWrite.insert(newArray);
|
||||
}
|
||||
}
|
||||
|
||||
bool changed = true;
|
||||
while (changed)
|
||||
{
|
||||
changed = false;
|
||||
for (auto &func : funcByName)
|
||||
{
|
||||
for (auto &callsFrom : func.second->callsFrom)
|
||||
{
|
||||
auto itF = funcByName.find(callsFrom);
|
||||
if (itF != funcByName.end())
|
||||
{
|
||||
for (auto &usedArray : itF->second->allUsedArrays)
|
||||
{
|
||||
auto itA = func.second->allUsedArrays.find(usedArray);
|
||||
if (itA == func.second->allUsedArrays.end())
|
||||
{
|
||||
changed = true;
|
||||
func.second->allUsedArrays.insert(usedArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
changed = true;
|
||||
while (changed)
|
||||
{
|
||||
changed = false;
|
||||
for (auto &func : funcByName)
|
||||
{
|
||||
for (auto &callsFrom : func.second->callsFrom)
|
||||
{
|
||||
auto itF = funcByName.find(callsFrom);
|
||||
if (itF != funcByName.end())
|
||||
{
|
||||
for (auto &usedArray : itF->second->usedArraysWrite)
|
||||
{
|
||||
auto itA = func.second->usedArraysWrite.find(usedArray);
|
||||
if (itA == func.second->usedArraysWrite.end())
|
||||
{
|
||||
changed = true;
|
||||
func.second->usedArraysWrite.insert(usedArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void createLinksBetweenFormalAndActualParams(map<string, vector<FuncInfo*>> &allFuncInfo, map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
|
||||
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
|
||||
map<string, vector<Messages>> &SPF_messages, bool keepFiles)
|
||||
{
|
||||
for (auto &funcsOnFile : allFuncInfo)
|
||||
{
|
||||
for (auto &func : funcsOnFile.second)
|
||||
{
|
||||
//printf("func %s :\n", func->funcName.c_str());
|
||||
const string &name = func->funcName;
|
||||
for (auto &caller : func->callsTo)
|
||||
for (int i = 0; i < caller->callsFromDetailed.size(); ++i)
|
||||
if (caller->callsFromDetailed[i].detailCallsFrom.first == name)
|
||||
addLinks(caller->callsFromDetailed[i].actualParams, func->funcParams, arrayLinksByFuncCalls);
|
||||
}
|
||||
}
|
||||
|
||||
#if DEB
|
||||
printf("BEFORE\n");
|
||||
//debug dump
|
||||
for (auto& elem : declaredArrays)
|
||||
{
|
||||
auto array = elem.second.first;
|
||||
auto flag = array->GetDistributeFlagVal();
|
||||
// int { DISTR = 0, NO_DISTR, SPF_PRIV, IO_PRIV } distFlagType;
|
||||
string flagS = "";
|
||||
if (flag == DIST::DISTR)
|
||||
flagS = "DISTR";
|
||||
else if (flag == DIST::NO_DISTR)
|
||||
flagS = "NO_DISTR";
|
||||
else if (flag == DIST::SPF_PRIV)
|
||||
flagS = "SPF_PRIV";
|
||||
else if (flag == DIST::IO_PRIV)
|
||||
flagS = "IO_PRIV";
|
||||
|
||||
printf("%s %s flag %s\n", array->GetShortName(), array->GetName(), flagS.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (keepFiles)
|
||||
{
|
||||
FILE *file = fopen("_arrayLinksByCalls.txt", "w");
|
||||
for (auto &elem : arrayLinksByFuncCalls)
|
||||
{
|
||||
fprintf(file, "%s -> ", elem.first->GetName().c_str());
|
||||
for (auto &rhs : elem.second)
|
||||
fprintf(file, " %s ", rhs->GetName().c_str());
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages);
|
||||
|
||||
//propagate distr state
|
||||
bool change = true;
|
||||
while (change)
|
||||
{
|
||||
change = false;
|
||||
for (auto &array : declaredArrays)
|
||||
{
|
||||
set<DIST::Array*> realArrayRefs;
|
||||
getRealArrayRefs(array.second.first, array.second.first, realArrayRefs, arrayLinksByFuncCalls);
|
||||
|
||||
if (realArrayRefs.size() && (*realArrayRefs.begin()) != array.second.first &&
|
||||
!(*realArrayRefs.begin())->IsNotDistribute() && array.second.first->IsNotDistribute())
|
||||
{
|
||||
array.second.first->SetDistributeFlag(DIST::DISTR);
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map<string, FuncInfo*> funcByName;
|
||||
createMapOfFunc(allFuncInfo, funcByName);
|
||||
aggregateUsedArrays(funcByName, arrayLinksByFuncCalls);
|
||||
|
||||
|
||||
#if DEB
|
||||
printf("AFTER\n");
|
||||
//debug dump
|
||||
for (auto &elem : declaredArrays)
|
||||
{
|
||||
auto array = elem.second.first;
|
||||
auto flag = array->GetDistributeFlagVal();
|
||||
// int { DISTR = 0, NO_DISTR, SPF_PRIV, IO_PRIV } distFlagType;
|
||||
string flagS = "";
|
||||
if (flag == DIST::DISTR)
|
||||
flagS = "DISTR";
|
||||
else if (flag == DIST::NO_DISTR)
|
||||
flagS = "NO_DISTR";
|
||||
else if (flag == DIST::SPF_PRIV)
|
||||
flagS = "SPF_PRIV";
|
||||
else if (flag == DIST::IO_PRIV)
|
||||
flagS = "IO_PRIV";
|
||||
|
||||
printf("%s %s flag %s\n", array->GetShortName(), array->GetName(), flagS.c_str());
|
||||
}
|
||||
printf("");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool detectMpiCalls(const map<string, vector<FuncInfo*>>& allFuncInfo, map<string, vector<Messages>>& SPF_messages)
|
||||
{
|
||||
bool retVal = false;
|
||||
|
||||
map<string, FuncInfo*> funcByName;
|
||||
createMapOfFunc(allFuncInfo, funcByName);
|
||||
|
||||
for (auto& byFile : allFuncInfo)
|
||||
{
|
||||
for (auto& func : byFile.second)
|
||||
{
|
||||
for (auto& callInfo: func->callsFromDetailed)
|
||||
{
|
||||
auto& callsFromThis = callInfo.detailCallsFrom;
|
||||
if (isMpiFunction(callsFromThis.first) && funcByName.find(callsFromThis.first) == funcByName.end())
|
||||
{
|
||||
retVal = true;
|
||||
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Detected mpi call, turn on special regime of paralyzing");
|
||||
__spf_printToLongBuf(messageR, R148);
|
||||
|
||||
SPF_messages[byFile.first].push_back(Messages(NOTE, callsFromThis.second, messageR, messageE, 1051));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void excludeArraysFromDistribution(const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>> declaredArrays,
|
||||
map<string, vector<LoopGraph*>>& loopGraph,
|
||||
vector<ParallelRegion*> parallelRegions,
|
||||
map<string, vector<Messages>>& SPF_messages,
|
||||
map<tuple<int, string, string>, DIST::Array*>& createdArrays,
|
||||
int sharedMemoryParallelization)
|
||||
{
|
||||
checkArraysMapping(loopGraph, SPF_messages, arrayLinksByFuncCalls);
|
||||
propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages);
|
||||
|
||||
if (sharedMemoryParallelization == 0)
|
||||
{
|
||||
for (int z = 0; z < parallelRegions.size(); ++z)
|
||||
filterArrayInCSRGraph(loopGraph, allFuncInfo, parallelRegions[z], arrayLinksByFuncCalls, SPF_messages);
|
||||
propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages);
|
||||
}
|
||||
|
||||
for (auto& loopByFile : loopGraph)
|
||||
{
|
||||
for (auto& loop : loopByFile.second)
|
||||
{
|
||||
loop->removeNonDistrArrays();
|
||||
loop->removeGraphData();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& funcByFile : allFuncInfo)
|
||||
for (auto& func : funcByFile.second)
|
||||
func->removeNonDistrArrays();
|
||||
|
||||
//restore
|
||||
for (int z = 0; z < parallelRegions.size(); ++z)
|
||||
{
|
||||
parallelRegions[z]->GetAllArraysToModify().cleanData();
|
||||
parallelRegions[z]->GetGraphToModify().ClearGraphCSR();
|
||||
parallelRegions[z]->GetReducedGraphToModify().ClearGraphCSR();
|
||||
}
|
||||
createdArrays.clear();
|
||||
}
|
||||
|
||||
void compliteArrayUsage(DIST::Arrays<int>& allArraysForRegion,
|
||||
map<tuple<int, string, string>, DIST::Array*>& createdArrays,
|
||||
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const map<DIST::Array*, tuple<int, string, string>>& tableOfUniqNamesByArray)
|
||||
{
|
||||
set<DIST::Array*> usedArraysLocal;
|
||||
usedArraysLocal.insert(allArraysForRegion.GetArrays().begin(), allArraysForRegion.GetArrays().end());
|
||||
|
||||
//add array that linked with used
|
||||
for (auto& used : usedArraysLocal)
|
||||
{
|
||||
set<DIST::Array*> allArrayRefs;
|
||||
getAllArrayRefs(used, used, allArrayRefs, arrayLinksByFuncCalls);
|
||||
|
||||
for (auto& array : allArrayRefs)
|
||||
{
|
||||
if (usedArraysLocal.find(array) == usedArraysLocal.end())
|
||||
{
|
||||
auto key = tableOfUniqNamesByArray.find(array);
|
||||
if (key != tableOfUniqNamesByArray.end())
|
||||
{
|
||||
createdArrays.insert(make_pair(key->second, key->first));
|
||||
allArraysForRegion.AddArrayToGraph(array);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void remoteNotUsedArrays(map<tuple<int, string, string>, DIST::Array*>& createdArrays,
|
||||
const set<DIST::Array*>& usedArraysAcrossRegions,
|
||||
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
|
||||
{
|
||||
//remove arrays that is not used
|
||||
map<tuple<int, string, string>, DIST::Array*> createdArraysNew;
|
||||
for (auto it = createdArrays.begin(); it != createdArrays.end(); ++it)
|
||||
{
|
||||
if (usedArraysAcrossRegions.find(it->second) != usedArraysAcrossRegions.end())
|
||||
createdArraysNew.insert(*it);
|
||||
else
|
||||
{
|
||||
set<DIST::Array*> realArrayRefs;
|
||||
getRealArrayRefs(it->second, it->second, realArrayRefs, arrayLinksByFuncCalls);
|
||||
|
||||
for (auto& array : realArrayRefs)
|
||||
{
|
||||
if (array == it->second)
|
||||
continue;
|
||||
|
||||
if (usedArraysAcrossRegions.find(array) != usedArraysAcrossRegions.end())
|
||||
createdArraysNew.insert(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
createdArrays = createdArraysNew;
|
||||
}
|
||||
57
Sapfor/_src/GraphCall/graph_calls_func.h
Normal file
57
Sapfor/_src/GraphCall/graph_calls_func.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include "graph_calls.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "../ParallelizationRegions/ParRegions.h"
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
class ArrayAccessInfo;
|
||||
}
|
||||
namespace DIST = Distribution;
|
||||
|
||||
namespace SAPFOR
|
||||
{
|
||||
class BasicBlock;
|
||||
}
|
||||
|
||||
int CreateCallGraphViz(const char *fileName, const std::map<std::string, std::vector<FuncInfo*>> &funcByFile, std::map<std::string, CallV> &V, std::vector<std::string> &E);
|
||||
int CreateFuncInfo(const char *fileName, const std::map<std::string, std::vector<FuncInfo*>> &funcByFile);
|
||||
std::string removeString(const std::string &toRemove, const std::string &inStr);
|
||||
FuncInfo* isUserFunctionInProject(const std::string &func);
|
||||
std::string convertToString(const FuncInfo *currFunc);
|
||||
void findDeadFunctionsAndFillCalls(std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, std::map<std::string, std::vector<Messages>> &allMessages, bool noPrint = false);
|
||||
void createLinksBetweenFormalAndActualParams(std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls,
|
||||
const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
|
||||
std::map<std::string, std::vector<Messages>> &SPF_messages, bool keepFiles = false);
|
||||
void createMapOfFunc(const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, std::map<std::string, FuncInfo*> &mapFuncInfo);
|
||||
void createMapOfFunc(const std::vector<FuncInfo*> &allFuncInfo, std::map<std::string, FuncInfo*> &mapFuncInfo);
|
||||
void createMapOfFunc(const std::vector<FuncInfo*> &allFuncInfo, std::map<std::pair<std::string, int>, FuncInfo*> &mapFuncInfo);
|
||||
FuncInfo* getFuncInfo(const std::map<std::string, FuncInfo*> &funcMap, const std::string &funcName);
|
||||
|
||||
void updateFuncInfo(const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo);
|
||||
void excludeArraysFromDistribution(const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> declaredArrays, std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::vector<ParallelRegion*> parallelRegions, std::map<std::string, std::vector<Messages>>& SPF_messages, std::map<std::tuple<int, std::string, std::string>, DIST::Array*>& createdArrays, int sharedMemoryParallelization = 0);
|
||||
|
||||
#if __SPF
|
||||
void functionAnalyzer(SgFile *file, std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, const std::vector<LoopGraph*> &loops, std::vector<Messages> &messagesForFile, std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& fullIR);
|
||||
int CheckFunctionsToInline(SgProject *proj, const std::map<std::string, int> &files, const char *fileName,
|
||||
std::map<std::string, std::vector<FuncInfo*>> &funcByFile, const std::map<std::string, std::vector<LoopGraph*>> &loopGraph,
|
||||
std::map<std::string, std::vector<Messages>> &allMessages, bool needToAddErrors,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, const std::vector<ParallelRegion*> ®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);
|
||||
#endif
|
||||
|
||||
1295
Sapfor/_src/GraphLoop/graph_loops.cpp
Normal file
1295
Sapfor/_src/GraphLoop/graph_loops.cpp
Normal file
File diff suppressed because it is too large
Load Diff
509
Sapfor/_src/GraphLoop/graph_loops.h
Normal file
509
Sapfor/_src/GraphLoop/graph_loops.h
Normal file
@@ -0,0 +1,509 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "../Utils/errors.h"
|
||||
#include "../Utils/types.h"
|
||||
#include "../Distribution/DvmhDirective.h"
|
||||
#include "../Distribution/Distribution.h"
|
||||
|
||||
struct DistrVariant;
|
||||
struct ParallelDirective;
|
||||
struct ParallelRegion;
|
||||
class Statement;
|
||||
struct FuncInfo;
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
class Array;
|
||||
}
|
||||
namespace DIST = Distribution;
|
||||
|
||||
void getRealArrayRefs(DIST::Array* addTo, DIST::Array* curr, std::set<DIST::Array*>& realArrayRefs, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
void getAllArrayRefs(DIST::Array* addTo, DIST::Array* curr, std::set<DIST::Array*>& realArrayRefs, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
|
||||
struct LoopGraph
|
||||
{
|
||||
private:
|
||||
std::vector<std::pair<DIST::Array*, DistrVariant*>> redistributeRules;
|
||||
LoopGraph* needToSwapWith;
|
||||
|
||||
//for local directive creating in MPI mode
|
||||
DIST::GraphCSR<int, double, attrType> accessGraph;
|
||||
DIST::GraphCSR<int, double, attrType> reducedAccessGraph;
|
||||
DataDirective dataDirectives;
|
||||
//
|
||||
|
||||
public:
|
||||
LoopGraph()
|
||||
{
|
||||
lineNumAfterLoop = lineNum = altLineNum = -1;
|
||||
perfectLoop = 0;
|
||||
hasGoto = false;
|
||||
hasPrints = false;
|
||||
hasUnknownArrayDep = false;
|
||||
hasUnknownScalarDep = false;
|
||||
hasUnknownArrayAssigns = false;
|
||||
hasNonRectangularBounds = false;
|
||||
hasIndirectAccess = false;
|
||||
withoutDistributedArrays = false;
|
||||
hasWritesToNonDistribute = false;
|
||||
hasUnknownDistributedMap = false;
|
||||
hasDifferentAlignRules = false;
|
||||
hasNonPureProcedures = false;
|
||||
hasDvmIntervals = false;
|
||||
hasStops = false;
|
||||
directive = NULL;
|
||||
oldDirective = NULL;
|
||||
directiveForLoop = NULL;
|
||||
region = NULL;
|
||||
needToSwapWith = NULL;
|
||||
countOfIters = 0;
|
||||
countOfIterNested = 1;
|
||||
loop = NULL;
|
||||
parent = NULL;
|
||||
userDvmDirective = NULL;
|
||||
startVal = endVal = stepVal = 0;
|
||||
calculatedCountOfIters = 0;
|
||||
executionTimeInSec = -1.0;
|
||||
inDvmhRegion = 0;
|
||||
isFor = false;
|
||||
inCanonicalFrom = false;
|
||||
hasAccessToSubArray = false;
|
||||
hasSubstringRefs = false;
|
||||
}
|
||||
|
||||
~LoopGraph()
|
||||
{
|
||||
needToSwapWith = NULL;
|
||||
if (directive != NULL)
|
||||
delete directive;
|
||||
|
||||
if (directiveForLoop != NULL)
|
||||
delete directiveForLoop;
|
||||
|
||||
for (int i = 0; i < children.size(); ++i)
|
||||
delete children[i];
|
||||
|
||||
calls.clear();
|
||||
readOpsArray.clear();
|
||||
readOps.clear();
|
||||
writeOps.clear();
|
||||
hasConflicts.clear();
|
||||
acrossOutAttribute.clear();
|
||||
accessGraph.ClearGraphCSR();
|
||||
reducedAccessGraph.ClearGraphCSR();
|
||||
}
|
||||
|
||||
void setForSwap(LoopGraph* with) { needToSwapWith = with; }
|
||||
|
||||
LoopGraph* getForSwap() const { return needToSwapWith; }
|
||||
|
||||
void clearForSwap()
|
||||
{
|
||||
for (auto& ch : children)
|
||||
ch->clearForSwap();
|
||||
needToSwapWith = NULL;
|
||||
}
|
||||
|
||||
bool hasLimitsToParallel() const
|
||||
{
|
||||
return hasUnknownArrayDep || hasUnknownScalarDep || hasGoto || hasPrints || (hasConflicts.size() != 0) || hasStops || hasNonPureProcedures ||
|
||||
hasUnknownArrayAssigns || hasNonRectangularBounds || hasIndirectAccess || hasWritesToNonDistribute || hasDifferentAlignRules || hasDvmIntervals ||
|
||||
!isFor || lastprivateScalars.size() || hasAccessToSubArray || hasSubstringRefs;
|
||||
}
|
||||
|
||||
bool hasLimitsToSplit() const
|
||||
{
|
||||
return hasGoto || hasStops || !isFor || hasPrints;
|
||||
}
|
||||
|
||||
bool hasLimitsToCombine() const
|
||||
{
|
||||
return hasGoto || hasStops || !isFor || hasPrints || linesOfCycle.size();
|
||||
}
|
||||
|
||||
void addConflictMessages(std::vector<Messages> *messages)
|
||||
{
|
||||
const int line = altLineNum > 0 ? altLineNum : lineNum;
|
||||
if (hasUnknownArrayDep)
|
||||
messages->push_back(Messages(NOTE, line, R113, L"unknown array dependency prevents parallelization of this loop", 3006));
|
||||
|
||||
if (hasUnknownScalarDep)
|
||||
messages->push_back(Messages(NOTE, line, R114, L"unknown scalar dependency prevents parallelization of this loop", 3006));
|
||||
|
||||
if (hasGoto)
|
||||
messages->push_back(Messages(NOTE, line, R115, L"internal/external moves via GOTO or EXIT operations prevent parallelization of this loop", 3006));
|
||||
|
||||
if (hasPrints)
|
||||
messages->push_back(Messages(NOTE, line, R116, L"IO operations prevent parallelization of this loop", 3006));
|
||||
|
||||
if (hasStops)
|
||||
messages->push_back(Messages(NOTE, line, R117, L"stop operations prevent parallelization of this loop", 3006));
|
||||
|
||||
if (hasConflicts.size() != 0)
|
||||
messages->push_back(Messages(NOTE, line, R118, L"conflict writes operations prevent parallelization of this loop", 3006));
|
||||
|
||||
if (hasUnknownArrayAssigns)
|
||||
messages->push_back(Messages(NOTE, line, R119, L"unknown array reference for writes prevent parallelization of this loop", 3006));
|
||||
|
||||
if (hasNonRectangularBounds)
|
||||
messages->push_back(Messages(NOTE, line, R144, L"non rectangular bounds prevent parallelization of this loop", 3006));
|
||||
|
||||
if (hasIndirectAccess)
|
||||
messages->push_back(Messages(NOTE, line, R120, L"indirect access by distributed array prevents parallelization of this loop", 3006));
|
||||
|
||||
if (hasWritesToNonDistribute)
|
||||
messages->push_back(Messages(NOTE, line, R121, L"writes to non distributed array prevents parallelization of this loop", 3006));
|
||||
|
||||
if (hasDifferentAlignRules)
|
||||
messages->push_back(Messages(NOTE, line, R122, L"different aligns between writes to distributed array prevents parallelization of this loop", 3006));
|
||||
|
||||
if (hasNonPureProcedures)
|
||||
messages->push_back(Messages(NOTE, line, R123, L"non pure procedures prevent parallelization of this loop", 3006));
|
||||
|
||||
if (hasDvmIntervals)
|
||||
messages->push_back(Messages(NOTE, line, R145, L"DVM intervals prevent parallelization of this loop", 3006));
|
||||
|
||||
if (!isFor || !inCanonicalFrom)
|
||||
messages->push_back(Messages(NOTE, line, R178, L"This type of loop is not supported by the system", 3006));
|
||||
|
||||
if (lastprivateScalars.size())
|
||||
messages->push_back(Messages(NOTE, line, R199, L"lastprivate scalar dependency prevents parallelization of this loop", 3006));
|
||||
}
|
||||
|
||||
void setNewRedistributeRules(const std::vector<std::pair<DIST::Array*, DistrVariant*>> &newRedistributeRules)
|
||||
{
|
||||
// set to top and for all childs
|
||||
redistributeRules = newRedistributeRules;
|
||||
for (int i = 0; i < children.size(); ++i)
|
||||
children[i]->setNewRedistributeRules(newRedistributeRules);
|
||||
}
|
||||
|
||||
DistrVariant* getRedistributeRule(const DIST::Array *arrayT) const
|
||||
{
|
||||
DistrVariant *retVal = NULL;
|
||||
|
||||
for (int i = 0; i < redistributeRules.size(); ++i)
|
||||
{
|
||||
if (redistributeRules[i].first == arrayT)
|
||||
{
|
||||
retVal = redistributeRules[i].second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool hasRedistribute() const { return redistributeRules.size(); }
|
||||
|
||||
ParallelDirective* recalculateParallelDirective()
|
||||
{
|
||||
std::vector<ParallelDirective*> baseDirs(perfectLoop);
|
||||
LoopGraph *next = this;
|
||||
for (int z = 0; z < perfectLoop; ++z)
|
||||
{
|
||||
baseDirs[z] = next->directiveForLoop;
|
||||
if (z != perfectLoop - 1)
|
||||
next = next->children[0];
|
||||
}
|
||||
|
||||
ParallelDirective *parDirective = baseDirs[0];
|
||||
for (int z = 1; z < baseDirs.size() && baseDirs[z]; ++z)
|
||||
{
|
||||
ParallelDirective *old = parDirective;
|
||||
parDirective = *parDirective + *baseDirs[z];
|
||||
|
||||
if (z != 1)
|
||||
delete old;
|
||||
}
|
||||
|
||||
oldDirective = directive;
|
||||
directive = parDirective;
|
||||
return directive;
|
||||
}
|
||||
|
||||
void restoreDirective()
|
||||
{
|
||||
if (oldDirective)
|
||||
{
|
||||
delete directive;
|
||||
directive = oldDirective;
|
||||
}
|
||||
|
||||
for (int i = 0; i < children.size(); ++i)
|
||||
children[i]->restoreDirective();
|
||||
}
|
||||
|
||||
void setRegionToChilds()
|
||||
{
|
||||
for (auto &loop : children)
|
||||
{
|
||||
loop->region = region;
|
||||
loop->setRegionToChilds();
|
||||
}
|
||||
}
|
||||
|
||||
void recalculatePerfect();
|
||||
|
||||
void setWithOutDistrFlagToFalse()
|
||||
{
|
||||
for (auto &loop : children)
|
||||
{
|
||||
loop->withoutDistributedArrays = false;
|
||||
loop->setWithOutDistrFlagToFalse();
|
||||
}
|
||||
}
|
||||
|
||||
void propagateUserDvmDir()
|
||||
{
|
||||
for (auto &loop : children)
|
||||
{
|
||||
if (loop->userDvmDirective == NULL)
|
||||
loop->userDvmDirective = userDvmDirective;
|
||||
loop->propagateUserDvmDir();
|
||||
}
|
||||
}
|
||||
|
||||
void propagateDvmhRegion(const int flag)
|
||||
{
|
||||
for (auto& loop : children)
|
||||
{
|
||||
loop->inDvmhRegion = flag;
|
||||
loop->propagateDvmhRegion(flag);
|
||||
}
|
||||
}
|
||||
|
||||
std::string genLoopArrayName(const std::string &funcName) const
|
||||
{
|
||||
return funcName + "_loop_" + std::to_string(lineNum);
|
||||
}
|
||||
|
||||
std::set<DIST::Array*> getAllArraysInLoop()
|
||||
{
|
||||
std::set<DIST::Array*> retVal(readOpsArray);
|
||||
for (auto &elem : writeOps)
|
||||
retVal.insert(elem.first);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void removeNonDistrArrays()
|
||||
{
|
||||
std::set<DIST::Array*> newUsedArrays;
|
||||
for (auto &elem : usedArrays)
|
||||
if (elem->GetDistributeFlagVal() == DIST::DISTR)
|
||||
newUsedArrays.insert(elem);
|
||||
usedArrays = newUsedArrays;
|
||||
|
||||
std::set<DIST::Array*> newUsedArraysW;
|
||||
for (auto &elem : usedArraysWrite)
|
||||
if (elem->GetDistributeFlagVal() == DIST::DISTR)
|
||||
newUsedArraysW.insert(elem);
|
||||
usedArraysWrite = newUsedArraysW;
|
||||
|
||||
readOpsArray.clear();
|
||||
readOps.clear();
|
||||
writeOps.clear();
|
||||
hasConflicts.clear();
|
||||
|
||||
for (auto &ch : children)
|
||||
ch->removeNonDistrArrays();
|
||||
}
|
||||
|
||||
void removeGraphData()
|
||||
{
|
||||
accessGraph.ClearGraphCSR();
|
||||
reducedAccessGraph.ClearGraphCSR();
|
||||
|
||||
for (auto& ch : children)
|
||||
ch->removeGraphData();
|
||||
}
|
||||
|
||||
void clearUserDirectives();
|
||||
|
||||
bool isArrayTemplatesTheSame(DIST::Array*& sameTemplate, const uint64_t regId, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls)
|
||||
{
|
||||
if (sharedMemoryParallelization != 0)
|
||||
return true;
|
||||
|
||||
std::set<DIST::Array*> usedForRegAccess;
|
||||
for (auto& array : writeOps)
|
||||
{
|
||||
std::set<DIST::Array*> realArrayRefs;
|
||||
getRealArrayRefs(array.first, array.first, realArrayRefs, arrayLinksByFuncCalls);
|
||||
for (auto& realArr : realArrayRefs)
|
||||
usedForRegAccess.insert(realArr);
|
||||
}
|
||||
|
||||
//read operations can be REMOTE_ACCESS
|
||||
/*for (auto& array : readOps)
|
||||
{
|
||||
std::set<DIST::Array*> realArrayRefs;
|
||||
getRealArrayRefs(array.first, array.first, realArrayRefs, arrayLinksByFuncCalls);
|
||||
for (auto& realArr : realArrayRefs)
|
||||
usedForRegAccess.insert(realArr);
|
||||
}*/
|
||||
|
||||
std::set<DIST::Array*> usedTemplates;
|
||||
for (auto& array : usedArrays)
|
||||
{
|
||||
std::set<DIST::Array*> realArrayRefs;
|
||||
getRealArrayRefs(array, array, realArrayRefs, arrayLinksByFuncCalls);
|
||||
for (auto& realArr : realArrayRefs)
|
||||
{
|
||||
if (usedForRegAccess.find(realArr) == usedForRegAccess.end())
|
||||
continue;
|
||||
|
||||
auto templ = realArr->GetTemplateArray(regId);
|
||||
//TODO: what about NULL?
|
||||
if (templ)
|
||||
usedTemplates.insert(templ);
|
||||
}
|
||||
}
|
||||
|
||||
if (usedArrays.size())
|
||||
{
|
||||
if (usedTemplates.size() == 0 || usedTemplates.size() > 1)
|
||||
return false;
|
||||
else
|
||||
sameTemplate = *usedTemplates.begin();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasParallelLoopsInChList();
|
||||
|
||||
DIST::GraphCSR<int, double, attrType>& getGraphToModify() { return accessGraph; }
|
||||
const DIST::GraphCSR<int, double, attrType>& getGraph() const { return accessGraph; }
|
||||
|
||||
DataDirective& getDataDirToModify() { return dataDirectives; }
|
||||
const DataDirective& getDataDir() const { return dataDirectives; }
|
||||
|
||||
void reduceAccessGraph();
|
||||
|
||||
void createVirtualTemplateLinks(const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, std::map<std::string, std::vector<Messages>>& SPF_messages, bool isMpiProgram = false);
|
||||
|
||||
bool hasParalleDirectiveBefore();
|
||||
|
||||
void analyzeParallelDirs();
|
||||
|
||||
void* getRealStat(const char* file) const;
|
||||
|
||||
public:
|
||||
int lineNum;
|
||||
int altLineNum;
|
||||
int lineNumAfterLoop;
|
||||
std::string fileName;
|
||||
int perfectLoop;
|
||||
int countOfIters; // calculated total with nested loops
|
||||
double countOfIterNested;
|
||||
double executionTimeInSec;
|
||||
int calculatedCountOfIters; // calculated for current loop
|
||||
|
||||
int startVal, endVal, stepVal;
|
||||
std::tuple<Expression*, Expression*, Expression*> startEndStepVals;
|
||||
|
||||
std::string loopSymbol;
|
||||
std::pair<Expression*, Expression*> startEndExpr;
|
||||
|
||||
bool hasGoto;
|
||||
std::vector<int> linesOfInternalGoTo;
|
||||
std::vector<int> linesOfExternalGoTo;
|
||||
std::vector<int> linesOfCycle;
|
||||
|
||||
bool hasPrints;
|
||||
std::set<int> linesOfIO;
|
||||
|
||||
bool hasStops;
|
||||
std::set<int> linesOfStop;
|
||||
|
||||
bool hasUnknownScalarDep;
|
||||
std::vector<int> linesOfScalarDep;
|
||||
|
||||
bool hasUnknownArrayDep;
|
||||
|
||||
bool hasUnknownArrayAssigns;
|
||||
|
||||
bool hasNonRectangularBounds;
|
||||
|
||||
bool hasIndirectAccess;
|
||||
|
||||
bool hasWritesToNonDistribute;
|
||||
|
||||
bool withoutDistributedArrays;
|
||||
|
||||
bool hasUnknownDistributedMap;
|
||||
|
||||
bool hasDifferentAlignRules;
|
||||
|
||||
bool hasNonPureProcedures;
|
||||
|
||||
bool hasDvmIntervals;
|
||||
// make sense only for NODIST regime
|
||||
bool hasAccessToSubArray;
|
||||
|
||||
bool hasSubstringRefs;
|
||||
|
||||
bool isFor;
|
||||
|
||||
bool inCanonicalFrom;
|
||||
|
||||
|
||||
std::vector<LoopGraph*> children;
|
||||
std::vector<LoopGraph*> funcChildren;
|
||||
LoopGraph *parent;
|
||||
std::vector<LoopGraph*> funcParents;
|
||||
|
||||
// PAIR<FUNC_NAME, LINE>
|
||||
std::vector<std::pair<std::string, int>> calls;
|
||||
|
||||
std::set<std::string> lastprivateScalars;
|
||||
std::set<std::string> privateScalars;
|
||||
|
||||
std::map<DIST::Array*, std::vector<ArrayOp>> readOpsForLoop;
|
||||
std::map<DIST::Array*, std::vector<ArrayOp>> writeOpsForLoop;
|
||||
|
||||
// agregated read and write operations by arrays
|
||||
std::set<DIST::Array*> readOpsArray;
|
||||
std::map<DIST::Array*, std::pair<std::vector<ArrayOp>, std::vector<bool>>> readOps;
|
||||
std::map<DIST::Array*, std::vector<ArrayOp>> writeOps;
|
||||
std::map<DIST::Array*, std::vector<ArrayOp>> remoteRegularReads;
|
||||
std::map<DIST::Array*, bool> hasConflicts;
|
||||
|
||||
std::set<DIST::Array*> acrossOutAttribute;
|
||||
|
||||
ParallelDirective *directive; // united directive for nested loops
|
||||
ParallelDirective *oldDirective; // save old directive for reverse
|
||||
ParallelDirective *directiveForLoop; // part of directive for loop
|
||||
Statement *userDvmDirective; // user's DVM PARALLEL directive
|
||||
|
||||
ParallelRegion *region;
|
||||
|
||||
Statement *loop;
|
||||
|
||||
std::set<DIST::Array*> usedArrays;// without NON DIST
|
||||
std::set<DIST::Array*> usedArraysAll;
|
||||
std::set<DIST::Array*> usedArraysWrite; // without NON DIST
|
||||
std::set<DIST::Array*> usedArraysWriteAll;
|
||||
|
||||
int inDvmhRegion; // 0 -unknown, -1 - no, 1 - yes
|
||||
};
|
||||
|
||||
void processLoopInformationForFunction(std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>>& loopInfo);
|
||||
void addToDistributionGraph(const std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>>& loopInfo, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
void selectFreeLoopsForParallelization(const std::vector<LoopGraph*>& loops, const std::string& funcName, bool isDistribute, const std::vector<ParallelRegion*>& regions, std::vector<Messages>& messagesForFile);
|
||||
|
||||
void convertToString(const LoopGraph* currLoop, std::string& result);
|
||||
int printLoopGraph(const char* fileName, const std::map<std::string, std::vector<LoopGraph*>>& loopGraph, bool withRegs = false);
|
||||
void checkCountOfIter(std::map<std::string, std::vector<LoopGraph*>>& loopGraph, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, std::map<std::string, std::vector<Messages>>& SPF_messages);
|
||||
|
||||
void createMapLoopGraph(const std::vector<LoopGraph*>& loops, std::map<int, LoopGraph*>& mapGraph);
|
||||
void updateLoopIoAndStopsByFuncCalls(std::map<std::string, std::vector<LoopGraph*>>& loopGraph, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
|
||||
void checkArraysMapping(const std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::map<std::string, std::vector<Messages>>& SPF_messages, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
void filterArrayInCSRGraph(std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::map<std::string, std::vector<FuncInfo*>>& allFuncs, ParallelRegion* reg, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, std::map<std::string, std::vector<Messages>>& messages);
|
||||
void swapLoopsForParallel(std::map<std::string, std::vector<LoopGraph*>>& loopGraph, std::map<std::string, std::vector<Messages>>& SPF_messages, const int rev);
|
||||
|
||||
1388
Sapfor/_src/GraphLoop/graph_loops_base.cpp
Normal file
1388
Sapfor/_src/GraphLoop/graph_loops_base.cpp
Normal file
File diff suppressed because it is too large
Load Diff
20
Sapfor/_src/GraphLoop/graph_loops_func.h
Normal file
20
Sapfor/_src/GraphLoop/graph_loops_func.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "graph_loops.h"
|
||||
#include "../Distribution/DvmhDirective.h"
|
||||
|
||||
struct SpfInterval;
|
||||
|
||||
void loopGraphAnalyzer(SgFile *file, std::vector<LoopGraph*> &loopGraph, const std::vector<SpfInterval*> &statisticTimes, std::vector<Messages> &messages, int sharedMemoryParallelization);
|
||||
void findAllRefsToLables(SgStatement *st, std::map<int, std::vector<int>> &labelsRef, bool includeWrite = true);
|
||||
std::map<LoopGraph*, ParallelDirective*> findAllDirectives(SgFile *file, const std::vector<LoopGraph*> &loops, const uint64_t regId);
|
||||
std::vector<std::tuple<DIST::Array*, std::vector<long>, std::pair<std::string, int>>> findAllSingleRemotes(SgFile *file, const uint64_t regId, std::vector<ParallelRegion*> ®ions);
|
||||
std::map<DIST::Array*, std::vector<long>> fillRemoteInParallel(Statement *st);
|
||||
bool hasThisIds(SgStatement *loop, std::set<int> &lines, const std::set<int> &IDs, const std::set<SgStatement*>* activeOps = NULL);
|
||||
bool checkRegionEntries(SgStatement *begin, SgStatement *end, const std::map<std::string, FuncInfo*> &funcMap, const std::vector<ParallelRegion*> ¶llelRegions, std::map<std::string, std::vector<Messages>> &SPF_messages);
|
||||
bool recSymbolFind(SgExpression *ex, const std::string &symb, const int var);
|
||||
void completeFillOfArrayUsageBetweenProc(const std::map<std::string, std::vector<LoopGraph*>>& loopGraph, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
|
||||
bool detectMpiCalls(SgProject* proj, std::map<std::string, std::vector<Messages>>& SPF_messages);
|
||||
int calculateLoopIters(SgExpression* start, SgExpression* end, SgExpression* step, std::tuple<int, int, int>& result);
|
||||
2573
Sapfor/_src/Inliner/inliner.cpp
Normal file
2573
Sapfor/_src/Inliner/inliner.cpp
Normal file
File diff suppressed because it is too large
Load Diff
12
Sapfor/_src/Inliner/inliner.h
Normal file
12
Sapfor/_src/Inliner/inliner.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
void callInliner(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo,
|
||||
std::vector<std::tuple<std::string, std::string, int>>& inDataProc,
|
||||
std::map<std::string, std::set<std::pair<std::string, int>>>& inDataChains,
|
||||
const std::set<std::string>& inDataChainsStart,
|
||||
std::map<std::string, std::vector<Messages>>& SPF_messages,
|
||||
const std::map<std::string, CommonBlock*>& commonBlocks);
|
||||
241
Sapfor/_src/LoopAnalyzer/allocations_prepoc.cpp
Normal file
241
Sapfor/_src/LoopAnalyzer/allocations_prepoc.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <assert.h>
|
||||
#include <set>
|
||||
|
||||
#include "dvm.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../Utils/errors.h"
|
||||
|
||||
using std::set;
|
||||
using std::pair;
|
||||
using std::map;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
void preprocess_allocates(SgFile *file)
|
||||
{
|
||||
const string currfile = file->filename();
|
||||
int funcNum = file->numberOfFunctions();
|
||||
|
||||
set<SgStatement*> allStats;
|
||||
for (auto st = file->firstStatement(); st != NULL; st = st->lexNext())
|
||||
allStats.insert(st);
|
||||
|
||||
for (int i = 0; i < funcNum; ++i)
|
||||
{
|
||||
SgStatement *st = file->functions(i);
|
||||
SgStatement *lastNode = st->lastNodeOfStmt();
|
||||
|
||||
while (st != lastNode)
|
||||
{
|
||||
if (st == NULL)
|
||||
{
|
||||
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
// save SgStatement PROC call to declaration attribute
|
||||
if (st->variant() == ALLOCATE_STMT || st->variant() == DEALLOCATE_STMT)
|
||||
{
|
||||
SgExpression *list = st->expr(0);
|
||||
set<SgStatement*> decls;
|
||||
while (list)
|
||||
{
|
||||
if (list->lhs()->variant() == ARRAY_REF)
|
||||
decls.insert(declaratedInStmt(OriginalSymbol(isSgArrayRefExp(list->lhs())->symbol())));
|
||||
else if (list->lhs()->variant() == RECORD_REF)
|
||||
{
|
||||
SgExpression* field = list->lhs()->lhs();
|
||||
if (field->variant() == ARRAY_REF)
|
||||
decls.insert(declaratedInStmt(OriginalSymbol(field->symbol())));
|
||||
else if (field->variant() == VAR_REF)
|
||||
decls.insert(declaratedInStmt(OriginalSymbol(field->symbol())));
|
||||
else
|
||||
printf(""); // TODO
|
||||
}
|
||||
|
||||
list = list->rhs();
|
||||
}
|
||||
|
||||
set<SgStatement*> altDecls;
|
||||
for (auto& decl : decls)
|
||||
{
|
||||
if (decl->fileName() != currfile)
|
||||
{
|
||||
const string fIncl = decl->fileName();
|
||||
for (auto& stat : allStats)
|
||||
if (stat->lineNumber() == decl->lineNumber() && stat->fileName() == fIncl && decl != stat)
|
||||
altDecls.insert(stat);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& alt : altDecls)
|
||||
decls.insert(alt);
|
||||
|
||||
char buf[256];
|
||||
for (auto& decl : decls)
|
||||
{
|
||||
decl->addAttribute(st->variant(), st, sizeof(SgStatement*));
|
||||
sprintf(buf, " attribute (%d %s) is added to declaration on line %d of %s file\n",
|
||||
st->lineNumber(), st->fileName(), decl->lineNumber(), decl->fileName());
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
|
||||
if (decls.size() == 0)
|
||||
{
|
||||
sprintf(buf, "ERROR at line %d %s: Can not find declarations for allocation on line %d\n", __LINE__, convertFileName(__FILE__).c_str(), st->lineNumber());
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
throw(-1);
|
||||
}
|
||||
}
|
||||
st = st->lexNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: extend ALLOC/DEALLOC moving
|
||||
//TODO: add support of different files
|
||||
// only one level of call is supported
|
||||
void moveAllocatesInterproc(const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
|
||||
{
|
||||
for (auto &array : arrayLinksByFuncCalls)
|
||||
{
|
||||
if (array.first->GetLocation().first == DIST::l_PARAMETER)
|
||||
{
|
||||
//check one level of calls
|
||||
bool ok = true;
|
||||
for (auto &elem : array.second)
|
||||
if (elem->GetLocation().first == DIST::l_PARAMETER)
|
||||
ok = false;
|
||||
|
||||
//move to all real arrays
|
||||
if (ok)
|
||||
{
|
||||
auto allPlaces = array.first->GetDeclInfo();
|
||||
for (auto &place : allPlaces)
|
||||
{
|
||||
if (SgFile::switchToFile(place.first) != -1)
|
||||
{
|
||||
SgStatement *decl = SgStatement::getStatementByFileAndLine(place.first, place.second);
|
||||
checkNull(decl, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
map<SgStatement*, set<SgStatement*>> needToAdd;
|
||||
for (auto &data : getAttributes<SgStatement*, SgStatement*>(decl, set<int>{ ALLOCATE_STMT }))
|
||||
{
|
||||
for (auto &realArray : array.second)
|
||||
{
|
||||
auto allPlacesR = realArray->GetDeclInfo();
|
||||
for (auto &placeR : allPlacesR)
|
||||
{
|
||||
//the same file
|
||||
if (placeR.first == place.first)
|
||||
{
|
||||
SgStatement* declR = SgStatement::getStatementByFileAndLine(placeR.first, placeR.second);
|
||||
checkNull(declR, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
needToAdd[declR].insert(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& toAdd : needToAdd)
|
||||
{
|
||||
for (auto& list : toAdd.second)
|
||||
{
|
||||
char buf[256];
|
||||
toAdd.first->addAttribute(list->variant(), list, sizeof(SgStatement*));
|
||||
sprintf(buf, " [INTERPROC] attribute is added to declaration on line %d\n", toAdd.first->lineNumber());
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map<string, map<int, set<SgStatement*>>> attrsForModules; // mod -> [ line -> decls]
|
||||
|
||||
//get module declarations
|
||||
for (int z = 0; z < CurrentProject->numberOfFiles(); ++z)
|
||||
{
|
||||
SgFile* file = &(CurrentProject->file(z));
|
||||
|
||||
vector<SgStatement*> modules;
|
||||
findModulesInFile(file, modules);
|
||||
|
||||
for (auto& mod : modules)
|
||||
{
|
||||
SgStatement* st = mod;
|
||||
SgStatement* end = mod->lastNodeOfStmt();
|
||||
string modName = mod->symbol()->identifier();
|
||||
|
||||
while (st != end)
|
||||
{
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
for (auto& data : getAttributes<SgStatement*, SgStatement*>(st, set<int>{ ALLOCATE_STMT, DEALLOCATE_STMT }))
|
||||
attrsForModules[modName][st->lineNumber()].insert(data);
|
||||
st = st->lexNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//synchronize module declarations
|
||||
for (int z = 0; z < CurrentProject->numberOfFiles(); ++z)
|
||||
{
|
||||
SgFile* file = &(CurrentProject->file(z));
|
||||
|
||||
vector<SgStatement*> modules;
|
||||
findModulesInFile(file, modules);
|
||||
|
||||
for (auto& mod : modules)
|
||||
{
|
||||
SgStatement* st = mod;
|
||||
SgStatement* end = mod->lastNodeOfStmt();
|
||||
string modName = mod->symbol()->identifier();
|
||||
|
||||
if (attrsForModules.find(modName) == attrsForModules.end())
|
||||
continue;
|
||||
|
||||
auto& info = attrsForModules[modName];
|
||||
while (st != end)
|
||||
{
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (info.find(st->lineNumber()) != info.end())
|
||||
{
|
||||
const set<SgStatement*>& decls = info[st->lineNumber()];
|
||||
|
||||
auto attrs = getAttributes<SgStatement*, SgStatement*>(st, set<int>{ ALLOCATE_STMT, DEALLOCATE_STMT });
|
||||
const set<SgStatement*> inAttr(attrs.begin(), attrs.end());
|
||||
|
||||
for (auto& data : decls)
|
||||
{
|
||||
if (inAttr.find(data) == inAttr.end())
|
||||
{
|
||||
char buf[256];
|
||||
st->addAttribute(data->variant(), data, sizeof(SgStatement*));
|
||||
|
||||
sprintf(buf, " [MODULE SYNC] attribute (%d %s) is added to declaration on line %d of %s file\n",
|
||||
data->lineNumber(), data->fileName(), st->lineNumber(), st->fileName());
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
st = st->lexNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
448
Sapfor/_src/LoopAnalyzer/dep_analyzer.cpp
Normal file
448
Sapfor/_src/LoopAnalyzer/dep_analyzer.cpp
Normal file
@@ -0,0 +1,448 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <assert.h>
|
||||
#include <chrono>
|
||||
|
||||
#include "dvm.h"
|
||||
#include "loop_analyzer.h"
|
||||
|
||||
#include "../Utils/utils.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../ParallelizationRegions/ParRegions_func.h"
|
||||
#include "../SageAnalysisTool/depGraph.h"
|
||||
#include "../SageAnalysisTool/OmegaForSage/include/lang-interf.h"
|
||||
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
using std::tuple;
|
||||
using std::map;
|
||||
using std::set;
|
||||
using std::make_pair;
|
||||
using std::make_tuple;
|
||||
using std::get;
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::chrono::high_resolution_clock;
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::milliseconds;
|
||||
|
||||
extern map<LoopGraph*, depGraph*> depInfoForLoopGraph;
|
||||
extern void initializeDepAnalysisForFunction(SgFile *file, SgStatement *func, const map<string, FuncInfo*> &allFuncs, vector<Messages> &messagesForFile);
|
||||
extern int staticPrivateAnalysis;
|
||||
extern bool fullDepGraph;
|
||||
|
||||
static const set<string> *currentNonDistrArrays = NULL;
|
||||
static map<SgSymbol*, string> varInOut;
|
||||
static map<SgExpression*, string> *currentCollection = NULL;
|
||||
|
||||
bool isRemovableDependence(const depNode *currNode, const set<string> &privVars)
|
||||
{
|
||||
bool result = true;
|
||||
bool varIn = false, varOut = false;
|
||||
|
||||
switch (currNode->typedep)
|
||||
{
|
||||
case WRONGDEP:
|
||||
result = false;
|
||||
break;
|
||||
case ARRAYDEP:
|
||||
if (currentNonDistrArrays && currentNonDistrArrays->size() > 0)
|
||||
{
|
||||
SgSymbol *vIn = OriginalSymbol(currNode->varin->symbol());
|
||||
SgSymbol *vOut = OriginalSymbol(currNode->varout->symbol());
|
||||
|
||||
auto found = varInOut.find(vIn);
|
||||
if (found == varInOut.end())
|
||||
found = varInOut.insert(found, make_pair(vIn, vIn->identifier()));
|
||||
varIn = currentNonDistrArrays->find(found->second) != currentNonDistrArrays->end();
|
||||
|
||||
found = varInOut.find(vOut);
|
||||
if (found == varInOut.end())
|
||||
found = varInOut.insert(found, make_pair(vOut, vOut->identifier()));
|
||||
varOut = currentNonDistrArrays->find(found->second) != currentNonDistrArrays->end();
|
||||
}
|
||||
//dont check if textual identically
|
||||
if ((!isEqExpressions(currNode->varin, currNode->varout, *currentCollection) || varIn || varOut) && (currNode->varin != currNode->varout))
|
||||
{
|
||||
// TODO: process all loop, not only top loop
|
||||
if (currNode->knowndist[1] == 0 || currNode->distance[1] != 0)
|
||||
{
|
||||
if (currNode->knowndist[1] == 0)
|
||||
result = false;
|
||||
}
|
||||
else if (varIn || varOut) // found dependencies between non ditributed arrays
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case PRIVATEDEP:
|
||||
case REDUCTIONDEP:
|
||||
break;
|
||||
case SCALARDEP:
|
||||
if (privVars.find(currNode->varin->symbol()->identifier()) == privVars.end())
|
||||
result = false;
|
||||
break;
|
||||
default:
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static SgStatement* getCurrentFunc(SgStatement *st)
|
||||
{
|
||||
while (st && st->variant() != PROG_HEDR && st->variant() != PROC_HEDR && st->variant() != FUNC_HEDR)
|
||||
st = st->controlParent();
|
||||
checkNull(st, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
return st;
|
||||
}
|
||||
|
||||
depGraph *getDependenciesGraph(const LoopGraph *currLoop, SgFile *file, const set<string> *privVars)
|
||||
{
|
||||
SgForStmt *currLoopRef = (SgForStmt*)currLoop->loop->GetOriginal();
|
||||
auto t = high_resolution_clock::now();
|
||||
|
||||
map<SgExpression*, string> tmpCollection;
|
||||
currentCollection = &tmpCollection;
|
||||
|
||||
set<string> tmpPriv;
|
||||
depGraph *depg = new depGraph(file, getCurrentFunc(currLoopRef), currLoopRef, privVars ? *privVars : tmpPriv);
|
||||
float elapsed = duration_cast<milliseconds>(high_resolution_clock::now() - t).count() / 1000.;
|
||||
if (elapsed > 1.0f)
|
||||
printf("SAPFOR: time of graph bulding for loop %d = %f sec\n", currLoop->lineNum, elapsed);
|
||||
currentCollection = NULL;
|
||||
return depg;
|
||||
}
|
||||
|
||||
//TODO: remove?
|
||||
static int isOnlyDef(SgStatement *loopSt, const map<SgStatement*, vector<DefUseList>> &defUseByPlace, const string &symb)
|
||||
{
|
||||
SgStatement *last = loopSt->lastNodeOfStmt();
|
||||
bool wasFoundSome = false;
|
||||
int count = 0;
|
||||
for (auto st = loopSt; st != last; st = st->lexNext())
|
||||
{
|
||||
auto it = defUseByPlace.find(st);
|
||||
if (it != defUseByPlace.end())
|
||||
{
|
||||
for (auto &elem : it->second)
|
||||
{
|
||||
if (elem.getVar() == symb)
|
||||
{
|
||||
wasFoundSome = true;
|
||||
if (elem.isUse())
|
||||
return -1;
|
||||
if (elem.isDef())
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!wasFoundSome)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static set<string> fillNestedReduction(LoopGraph* currLoop)
|
||||
{
|
||||
set<string> redVars;
|
||||
tryToFindPrivateInAttributes(currLoop->loop, redVars, true, true);
|
||||
|
||||
int lastPerfect = currLoop->perfectLoop;
|
||||
currLoop = currLoop->parent;
|
||||
|
||||
while (currLoop && currLoop->perfectLoop == lastPerfect + 1)
|
||||
{
|
||||
tryToFindPrivateInAttributes(currLoop->loop, redVars, true, true);
|
||||
|
||||
lastPerfect = currLoop->perfectLoop;
|
||||
currLoop = currLoop->parent;
|
||||
}
|
||||
|
||||
return redVars;
|
||||
}
|
||||
|
||||
static SgExpression *startS = NULL, *endS = NULL;
|
||||
static SgExpression *startS_save = NULL, *endS_save = NULL;
|
||||
|
||||
// try to find dependencies: reductions and privates for scalar
|
||||
// and regular and other for arrrays
|
||||
//TODO: add optimization - dont call omega test for arrays many times
|
||||
void tryToFindDependencies(LoopGraph *currLoop, const map<int, pair<SgForStmt*, pair<set<string>, set<string>>>> &allLoops,
|
||||
set<SgStatement*> &funcWasInit, SgFile *file, vector<ParallelRegion*> regions,
|
||||
vector<Messages> *currMessages,
|
||||
map<SgExpression*, string> &collection,
|
||||
const map<string, FuncInfo*> &allFuncs, const map<SgStatement*, vector<DefUseList>> &defUseByPlace)
|
||||
{
|
||||
auto it = allLoops.find(currLoop->lineNum);
|
||||
if (it == allLoops.end())
|
||||
return;
|
||||
|
||||
map<int, SgForStmt*> localAllLoopMap;
|
||||
for (auto &elem : allLoops)
|
||||
localAllLoopMap.insert(make_pair(elem.first, elem.second.first));
|
||||
|
||||
ParallelRegion *currReg = getRegionByLine(regions, it->second.first->fileName(), currLoop->lineNum);
|
||||
|
||||
if (currReg && currLoop->hasLimitsToParallel() == false || fullDepGraph)
|
||||
{
|
||||
SgForStmt *currLoopRef = it->second.first;
|
||||
set<string> redVars = fillNestedReduction(currLoop);
|
||||
|
||||
bool onlyOneStep = false;
|
||||
// if identical
|
||||
/*string startL = string(currLoopRef->start()->unparse());
|
||||
string endL = string(currLoopRef->end()->unparse());
|
||||
if (startL == endL)
|
||||
onlyOneStep = true;*/
|
||||
// XXX: turn off this "optimization"
|
||||
|
||||
//make unknown iters count for better analysis
|
||||
bool interChanged = false;
|
||||
if (currLoop->countOfIters == 1)
|
||||
{
|
||||
interChanged = true;
|
||||
if (!startS)
|
||||
startS = new SgExpression(VAR_REF, new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "_tmp1_")));
|
||||
if (!endS)
|
||||
endS = new SgExpression(VAR_REF, new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "_tmp2_")));
|
||||
|
||||
startS_save = currLoopRef->start();
|
||||
endS_save = currLoopRef->end();
|
||||
|
||||
currLoopRef->setStart(*startS);
|
||||
currLoopRef->setEnd(*endS);
|
||||
}
|
||||
|
||||
const set<string> &privVars = it->second.second.first;
|
||||
const set<string> &nonDistrArrays = it->second.second.second;
|
||||
|
||||
SgStatement *func = getFuncStat(currLoopRef);
|
||||
if (funcWasInit.find(func) == funcWasInit.end())
|
||||
{
|
||||
funcWasInit.insert(func);
|
||||
initializeDepAnalysisForFunction(file, func, allFuncs, *currMessages);
|
||||
}
|
||||
|
||||
currentNonDistrArrays = &nonDistrArrays;
|
||||
currentCollection = &collection;
|
||||
depGraph *depg = getDependenciesGraph(currLoop, file, &privVars);
|
||||
|
||||
if (interChanged)
|
||||
{
|
||||
currLoopRef->setStart(*startS_save);
|
||||
currLoopRef->setEnd(*endS_save);
|
||||
}
|
||||
|
||||
currentNonDistrArrays = NULL;
|
||||
currentCollection = NULL;
|
||||
|
||||
/*auto t = high_resolution_clock::now();
|
||||
depGraph *depg = new depGraph(file, getCurrentFunc(currLoopRef), currLoopRef, privVars);
|
||||
float elapsed = duration_cast<milliseconds>(high_resolution_clock::now() - t).count() / 1000.;
|
||||
if (elapsed > 1.0f)
|
||||
printf("SAPFOR: time of graph bulding for loop %d = %f sec\n", currLoop->lineNum, elapsed);*/
|
||||
|
||||
if (depg)
|
||||
{
|
||||
const std::vector<depNode*> &nodes = depg->getNodes();
|
||||
//vector<const depNode*> privatesToAdd;
|
||||
vector<const depNode*> reductionsToAdd;
|
||||
vector<const depNode*> unknownScalarDep;
|
||||
|
||||
bool findUnknownDepLen = false;
|
||||
map<SgSymbol*, tuple<int, int, int>> acrossToAdd;
|
||||
|
||||
bool varIn = false, varOut = false;
|
||||
bool isEqual = false;
|
||||
|
||||
for (int k = 0; k < nodes.size(); ++k)
|
||||
{
|
||||
const depNode *currNode = nodes[k];
|
||||
switch (currNode->typedep)
|
||||
{
|
||||
case WRONGDEP:
|
||||
break;
|
||||
case ARRAYDEP:
|
||||
if (nonDistrArrays.size() > 0)
|
||||
{
|
||||
SgSymbol *vIn = OriginalSymbol(currNode->varin->symbol());
|
||||
SgSymbol *vOut = OriginalSymbol(currNode->varout->symbol());
|
||||
|
||||
auto found = varInOut.find(vIn);
|
||||
if (found == varInOut.end())
|
||||
found = varInOut.insert(found, make_pair(vIn, vIn->identifier()));
|
||||
varIn = nonDistrArrays.find(found->second) != nonDistrArrays.end();
|
||||
|
||||
found = varInOut.find(vOut);
|
||||
if (found == varInOut.end())
|
||||
found = varInOut.insert(found, make_pair(vOut, vOut->identifier()));
|
||||
varOut = nonDistrArrays.find(found->second) != nonDistrArrays.end();
|
||||
}
|
||||
|
||||
isEqual = isEqExpressions(currNode->varin, currNode->varout, collection);
|
||||
//dont check if textual identically
|
||||
if ((!isEqual || varIn || varOut) && (currNode->varin != currNode->varout))
|
||||
{
|
||||
// TODO: process all loop, not only top loop
|
||||
if (currNode->knowndist[1] == 0 || currNode->distance[1] != 0)
|
||||
{
|
||||
if (currNode->knowndist[1] == 0)
|
||||
{
|
||||
if (!findUnknownDepLen)
|
||||
{
|
||||
auto message = currNode->createDepMessagebetweenArrays();
|
||||
wstring depMessageEng = to_wstring(message.first), depMessageRus = to_wstring(message.second);
|
||||
|
||||
depMessageEng += L" with unknown distance in loop on line " + std::to_wstring(currLoopRef->lineNumber()) + L" prevents parallelization";
|
||||
depMessageRus += L"#" + std::to_wstring(currLoopRef->lineNumber());
|
||||
|
||||
currMessages->push_back(Messages(NOTE, currNode->stmtin->lineNumber(), L"R124:" + depMessageRus, depMessageEng, 3006));
|
||||
|
||||
// __spf_print only first unknown dep length
|
||||
findUnknownDepLen = true;
|
||||
if (!onlyOneStep)
|
||||
currLoop->hasUnknownArrayDep = true;
|
||||
}
|
||||
}
|
||||
else if (!findUnknownDepLen) //currNode->distance[1] != 0
|
||||
{
|
||||
const ddnature nature = (ddnature)currNode->kinddep;
|
||||
int position = -1;
|
||||
if (nature == ddflow)
|
||||
position = 0;
|
||||
else if (nature == ddanti)
|
||||
position = 1;
|
||||
|
||||
if (position != -1)
|
||||
{
|
||||
SgSymbol *arrayS = OriginalSymbol(currNode->varin->symbol());
|
||||
SgArrayRefExp *arrayRef = (SgArrayRefExp*)(currNode->varin);
|
||||
|
||||
bool existSubs = false;
|
||||
|
||||
auto it = acrossToAdd.find(arrayS);
|
||||
if (it == acrossToAdd.end())
|
||||
{
|
||||
int subsPos = -1;
|
||||
SgSymbol *doName = currLoopRef->symbol();
|
||||
for (int z = 0; z < arrayRef->numberOfSubscripts() && !existSubs; ++z)
|
||||
{
|
||||
existSubs = checkExistence(arrayRef->subscript(z), doName->identifier());
|
||||
if (existSubs)
|
||||
subsPos = z;
|
||||
}
|
||||
|
||||
if (existSubs)
|
||||
it = acrossToAdd.insert(it, make_pair(arrayS, make_tuple(0, 0, subsPos)));
|
||||
}
|
||||
else
|
||||
existSubs = true;
|
||||
|
||||
if (existSubs)
|
||||
{
|
||||
if (position == 0)
|
||||
get<0>(it->second) = std::max(get<0>(it->second), abs((int)currNode->distance[1]));
|
||||
else
|
||||
get<1>(it->second) = std::max(get<1>(it->second), abs((int)currNode->distance[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!isEqual && (varIn || varOut)) // found dependencies between non ditributed arrays
|
||||
{
|
||||
if (currNode->knowndist[1] == 0 || currNode->distance[1] != 0)
|
||||
{
|
||||
if (!findUnknownDepLen)
|
||||
{
|
||||
auto message = currNode->createDepMessagebetweenArrays();
|
||||
wstring depMessageEng = to_wstring(message.first), depMessageRus = to_wstring(message.second);
|
||||
depMessageEng += L" prevents parallelization";
|
||||
currMessages->push_back(Messages(NOTE, currNode->stmtin->lineNumber(), L"R124:" + depMessageRus, depMessageEng, 3006));
|
||||
|
||||
// __spf_print only first unknown dep length
|
||||
findUnknownDepLen = true;
|
||||
if (!onlyOneStep)
|
||||
currLoop->hasUnknownArrayDep = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//currNode->displayDep();
|
||||
break;
|
||||
case PRIVATEDEP: //privates detected by PRIVATE_ANALYSIS_IR
|
||||
/*if (privVars.find(currNode->varin->symbol()->identifier()) == privVars.end())
|
||||
privatesToAdd.push_back(currNode);
|
||||
//unknownScalarDep.push_back(currNode); */
|
||||
break;
|
||||
case REDUCTIONDEP:
|
||||
if (currLoop->privateScalars.find(currNode->varin->symbol()->identifier()) == currLoop->privateScalars.end() &&
|
||||
redVars.find(currNode->varin->symbol()->identifier()) == redVars.end())
|
||||
reductionsToAdd.push_back(currNode);
|
||||
break;
|
||||
case SCALARDEP:
|
||||
if (currLoop->privateScalars.find(currNode->varin->symbol()->identifier()) == currLoop->privateScalars.end() &&
|
||||
redVars.find(currNode->varin->symbol()->identifier()) == redVars.end())
|
||||
unknownScalarDep.push_back(currNode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!onlyOneStep)
|
||||
{
|
||||
//NOTE: do it via PRIVATE_ANALYSIS_IR
|
||||
//addPrivatesToLoops(currLoop, privatesToAdd, localAllLoopMap, *currMessages);
|
||||
addReductionsToLoops(currLoop, reductionsToAdd, localAllLoopMap, *currMessages);
|
||||
if (!findUnknownDepLen && !currLoop->hasLimitsToParallel())
|
||||
addAcrossToLoops(currLoop, acrossToAdd, localAllLoopMap, *currMessages);
|
||||
|
||||
currLoop->hasUnknownScalarDep = (unknownScalarDep.size() != 0);
|
||||
for (int k = 0; k < unknownScalarDep.size(); ++k)
|
||||
{
|
||||
__spf_print(1, " unknown scalar dependencies by '%s' on line %d (try to specify its type)\n",
|
||||
unknownScalarDep[k]->varin->symbol()->identifier(), unknownScalarDep[k]->stmtin->lineNumber());
|
||||
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"unknown scalar dependencies by '%s' (try to specify its type)", to_wstring(unknownScalarDep[k]->varin->symbol()->identifier()).c_str());
|
||||
__spf_printToLongBuf(messageR, R112, to_wstring(unknownScalarDep[k]->varin->symbol()->identifier()).c_str());
|
||||
|
||||
currMessages->push_back(Messages(WARR, unknownScalarDep[k]->stmtin->lineNumber(), messageR, messageE, 3005));
|
||||
|
||||
currLoop->linesOfScalarDep.push_back(unknownScalarDep[k]->stmtin->lineNumber());
|
||||
}
|
||||
}
|
||||
|
||||
depInfoForLoopGraph[currLoop] = depg;
|
||||
if (currLoop->hasLimitsToParallel())
|
||||
currLoop->addConflictMessages(currMessages);
|
||||
}
|
||||
}
|
||||
else if (currReg && currLoop->hasLimitsToParallel())
|
||||
{
|
||||
// loop has limits
|
||||
currLoop->addConflictMessages(currMessages);
|
||||
}
|
||||
|
||||
for (int k = 0; k < currLoop->children.size(); ++k)
|
||||
tryToFindDependencies(currLoop->children[k], allLoops, funcWasInit, file, regions, currMessages, collection, allFuncs, defUseByPlace);
|
||||
}
|
||||
2641
Sapfor/_src/LoopAnalyzer/loop_analyzer.cpp
Normal file
2641
Sapfor/_src/LoopAnalyzer/loop_analyzer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
104
Sapfor/_src/LoopAnalyzer/loop_analyzer.h
Normal file
104
Sapfor/_src/LoopAnalyzer/loop_analyzer.h
Normal file
@@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
#include "../ParallelizationRegions/ParRegions.h"
|
||||
#include "../SageAnalysisTool/depInterfaceExt.h"
|
||||
#include "../Utils/AstWrapper.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
|
||||
#include "dvm.h"
|
||||
|
||||
typedef std::pair<std::pair<int, int>, std::pair<int, int>> attrType;
|
||||
namespace DIST = Distribution;
|
||||
|
||||
enum REGIME { DATA_DISTR, COMP_DISTR, REMOTE_ACC, ARRAY_ACC_CORNER, SHARED_MEMORY_PAR, UNDEF };
|
||||
|
||||
// loop_analyzer.cpp
|
||||
bool checkExistence(SgExpression *exp, const std::string& doName);
|
||||
|
||||
void loopAnalyzer(SgFile *file,
|
||||
std::vector<ParallelRegion*> ®ions,
|
||||
std::map<std::tuple<int, std::string, std::string>, DIST::Array*> &createdArrays,
|
||||
std::vector<Messages> &messagesForFile,
|
||||
REGIME regime,
|
||||
const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo,
|
||||
const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
|
||||
const std::map<SgStatement*, std::set<std::tuple<int, std::string, std::string>>> &declaratedArraysSt,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls,
|
||||
const std::map<SgStatement*, std::vector<DefUseList>> &defUseByPlace,
|
||||
bool skipDeps, std::vector<LoopGraph*> *loopGraph = NULL);
|
||||
|
||||
void fillFromModule(SgSymbol* s, const std::map<std::string, std::set<std::string>>& privatesByModule, std::set<std::string>& privates);
|
||||
|
||||
std::vector<std::pair<Expression*, Expression*>> getArraySizes(std::vector<std::pair<int, int>>& sizes, SgSymbol* symb, SgStatement* decl,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
|
||||
|
||||
void arrayAccessAnalyzer(SgFile *file, std::vector<Messages> &messagesForFile,
|
||||
const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
|
||||
REGIME regime);
|
||||
|
||||
void processLoopInformationForFunction(std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>> &loopInfo);
|
||||
void addToDistributionGraph(const std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>> &loopInfo, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls);
|
||||
|
||||
void printBlanks(const int sizeOfBlank, const int countOfBlanks);
|
||||
bool isIntrinsic(const char *funName);
|
||||
|
||||
std::tuple<int, std::string, std::string> getUniqName(const std::map<std::string, SgStatement*> &commonBlocks, SgStatement *decl, SgSymbol *symb);
|
||||
std::string getShortName(const std::tuple<int, std::string, std::string> &uniqKey);
|
||||
|
||||
void insertSpfAnalysisBeforeParalleLoops(const std::vector<LoopGraph*> &loops);
|
||||
void recalculateArraySizes(std::set<DIST::Array*> &arraysDone, const std::set<DIST::Array*> &allArrays, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
|
||||
int getSizeOfType(SgType* t);
|
||||
|
||||
// dep_analyzer.cpp
|
||||
void tryToFindDependencies(LoopGraph *currLoop, const std::map<int, std::pair<SgForStmt*, std::pair<std::set<std::string>, std::set<std::string>>>> &allLoops,
|
||||
std::set<SgStatement*> &funcWasInit, SgFile *file, std::vector<ParallelRegion*> regions, std::vector<Messages> *currMessages,
|
||||
std::map<SgExpression*, std::string> &collection, const std::map<std::string, FuncInfo*> &allFuncs,
|
||||
const std::map<SgStatement*, std::vector<DefUseList>> &defUseByPlace);
|
||||
depGraph *getDependenciesGraph(const LoopGraph *currLoop, SgFile *file, const std::set<std::string> *privVars = NULL);
|
||||
|
||||
// allocations_prepoc.cpp
|
||||
void preprocess_allocates(SgFile *file);
|
||||
void moveAllocatesInterproc(const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
|
||||
// spf_directive_preproc.cpp
|
||||
bool preprocess_spf_dirs(SgFile *file, const std::map<std::string, CommonBlock*> &commonBlocks, std::vector<Messages> &messagesForFile, const std::set<std::string>& allFileNames, std::map<std::pair<std::string, int>, std::set<SgStatement*>>& usersDirectives);
|
||||
bool check_par_reg_dirs(SgFile *file, std::vector<Messages> &messagesForFile);
|
||||
|
||||
void revertion_spf_dirs(SgFile *file,
|
||||
std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> declaredArrays,
|
||||
std::map<SgStatement*, std::set<std::tuple<int, std::string, std::string>>> declaratedArraysSt);
|
||||
void addAcrossToLoops(LoopGraph *topLoop, const std::map<SgSymbol*, std::tuple<int, int, int>> &acrossToAdd,
|
||||
const std::map<int, SgForStmt*> &allLoops,
|
||||
std::vector<Messages> &currMessages);
|
||||
void addPrivatesToLoops(LoopGraph *currLoop, const std::vector<const depNode*> &privatesToAdd,
|
||||
const std::map<int, SgForStmt*> &allLoops,
|
||||
std::vector<Messages> &currMessages);
|
||||
void addReductionsToLoops(LoopGraph *currLoop, const std::vector<const depNode*> &reductionsToAdd,
|
||||
const std::map<int, SgForStmt*> &allLoops,
|
||||
std::vector<Messages> &currMessages);
|
||||
void fillVars(SgExpression *exp, const std::set<int> &types, std::set<SgSymbol*> &identifierList, std::vector<SgExpression*> &funcCalls);
|
||||
|
||||
// TODO: from remote_access.cpp, may be need to move
|
||||
bool isNeedToConvertIfCondition(SgExpression* ex);
|
||||
void addRemotesToDir(const std::pair<SgForStmt*, LoopGraph*> *under_dvm_dir, const std::map<std::string, ArrayRefExp*> &uniqRemotes);
|
||||
void fillRemoteFromDir(SgExpression* ex, std::vector<SgExpression*>& remotes);
|
||||
|
||||
template<int NUM> bool createRemoteDir(SgStatement *st, const std::map<std::string, FuncInfo*>& funcMap, const std::map<int, LoopGraph*> &sortedLoopGraph, const DIST::Arrays<int> &allArrays,
|
||||
const DataDirective &data, const std::vector<int> &currVar, const uint64_t regionId, std::vector<Messages> &currMessages,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls);
|
||||
void groupActualAndRemote(SgFile* file, bool revert = false);
|
||||
|
||||
std::vector<SgStatement*> filterUserSpf(const std::vector<SgStatement*>& toFilter, bool with_omp = true);
|
||||
|
||||
// ArrayAnalysis.cpp
|
||||
int getAllDeclaredArrays(SgFile *file, std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>> &declaredArrays,
|
||||
std::map<SgStatement*, std::set<std::tuple<int, std::string, std::string>>> &declaratedArraysSt, std::map<std::string, std::vector<Messages>> &currMessages,
|
||||
const std::vector<ParallelRegion*> ®ions, const std::map<std::string, int>& distrStateFromGUI);
|
||||
896
Sapfor/_src/ParallelizationRegions/ParRegions.cpp
Normal file
896
Sapfor/_src/ParallelizationRegions/ParRegions.cpp
Normal file
@@ -0,0 +1,896 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "dvm.h"
|
||||
#include "ParRegions.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../GraphCall/graph_calls_func.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "../Distribution/Distribution.h"
|
||||
#include "../ExpressionTransform/expr_transform.h"
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::pair;
|
||||
using std::make_pair;
|
||||
using std::map;
|
||||
using std::set;
|
||||
using std::wstring;
|
||||
|
||||
extern void createMapLoopGraph(map<int, LoopGraph*> &sortedLoopGraph, const vector<LoopGraph*> *loopGraph);
|
||||
|
||||
static map<string, int> regionIdByName;
|
||||
static map<string, ParallelRegion*> regionByName;
|
||||
|
||||
static int regionIdConuter = 1;
|
||||
|
||||
void clearRegionStaticData()
|
||||
{
|
||||
regionIdByName.clear();
|
||||
regionByName.clear();
|
||||
regionIdConuter = 1;
|
||||
}
|
||||
|
||||
|
||||
static inline void extendRegionInfo(SgStatement *st, map<string, pair<Statement*, Statement*>> &startEnd, map<string, pair<int, int>> &lines_, bool addEndSt = false)
|
||||
{
|
||||
auto it_st_en = startEnd.find(st->fileName());
|
||||
if (it_st_en == startEnd.end())
|
||||
{
|
||||
startEnd.insert(it_st_en, make_pair(st->fileName(), make_pair<Statement*, Statement*>(new Statement(st), NULL)));
|
||||
lines_[st->fileName()] = make_pair(st->lineNumber(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addEndSt)
|
||||
{
|
||||
Statement *toAdd = new Statement(st);
|
||||
it_st_en->second.second = toAdd;
|
||||
}
|
||||
lines_[st->fileName()].second = st->lineNumber();
|
||||
}
|
||||
}
|
||||
|
||||
static void findFuncCalls(SgExpression *ex, set<string> &calls, const string &prefix, const map<string, FuncInfo*>& mapFuncs)
|
||||
{
|
||||
if (ex == NULL)
|
||||
return;
|
||||
|
||||
if (ex->variant() == FUNC_CALL)
|
||||
{
|
||||
string fullName = ex->symbol()->identifier();
|
||||
//check contains
|
||||
if (mapFuncs.find(prefix + fullName) != mapFuncs.end())
|
||||
fullName = prefix + fullName;
|
||||
calls.insert(fullName);
|
||||
}
|
||||
|
||||
findFuncCalls(ex->lhs(), calls, prefix, mapFuncs);
|
||||
findFuncCalls(ex->rhs(), calls, prefix, mapFuncs);
|
||||
}
|
||||
|
||||
static inline SgStatement* getParentStat(SgStatement *st)
|
||||
{
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
SgStatement *iterator = st;
|
||||
|
||||
while (iterator->variant() != PROG_HEDR && iterator->variant() != PROC_HEDR && iterator->variant() != FUNC_HEDR)
|
||||
iterator = iterator->controlParent();
|
||||
|
||||
while (iterator->controlParent()->variant() == PROG_HEDR || iterator->controlParent()->variant() == PROC_HEDR || iterator->controlParent()->variant() == FUNC_HEDR)
|
||||
iterator = iterator->controlParent();
|
||||
|
||||
return iterator;
|
||||
}
|
||||
|
||||
static void updateRegionInfo(SgStatement *st, map<string, pair<Statement*, Statement*>> &startEnd, map<string, pair<int, int>> &lines_,
|
||||
set<string> &funcCallFromReg, const map<string, FuncInfo*> &mapFuncs)
|
||||
{
|
||||
string containsPrefix = "";
|
||||
SgStatement *st_ps = getParentStat(st);
|
||||
|
||||
if (st_ps->variant() == PROC_HEDR || st_ps->variant() == PROG_HEDR || st_ps->variant() == FUNC_HEDR)
|
||||
containsPrefix = st_ps->symbol()->identifier() + string(".");
|
||||
|
||||
extendRegionInfo(st, startEnd, lines_);
|
||||
if (st->variant() == PROC_STAT)
|
||||
{
|
||||
string fullName = st->symbol()->identifier();
|
||||
//check contains
|
||||
if (mapFuncs.find(containsPrefix + fullName) != mapFuncs.end())
|
||||
fullName = containsPrefix + fullName;
|
||||
funcCallFromReg.insert(fullName);
|
||||
}
|
||||
|
||||
for (int z = 0; z < 3; ++z)
|
||||
findFuncCalls(st->expr(z), funcCallFromReg, containsPrefix, mapFuncs);
|
||||
}
|
||||
|
||||
static void fillArrayNamesInReg(set<string> &usedArrayInRegion, SgExpression *exp)
|
||||
{
|
||||
if (exp)
|
||||
{
|
||||
if (exp->variant() == ARRAY_REF && OriginalSymbol(exp->symbol()))
|
||||
usedArrayInRegion.insert(OriginalSymbol(exp->symbol())->identifier());
|
||||
|
||||
fillArrayNamesInReg(usedArrayInRegion, exp->lhs());
|
||||
fillArrayNamesInReg(usedArrayInRegion, exp->rhs());
|
||||
}
|
||||
}
|
||||
|
||||
static bool filterUserDirectives(set<string> &usedArrayInRegion, vector<Statement*> &userDvmDirs, vector<Statement*> &userDvmDirsF)
|
||||
{
|
||||
vector<Statement*> filtered;
|
||||
bool changed = false;
|
||||
for (auto &distr : userDvmDirs)
|
||||
{
|
||||
set<string> usedIndir;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
fillArrayNamesInReg(usedIndir, distr->GetOriginal()->expr(i));
|
||||
|
||||
bool ok = false;
|
||||
for (auto &elem : usedIndir)
|
||||
{
|
||||
if (usedArrayInRegion.find(elem) != usedArrayInRegion.end())
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
usedArrayInRegion.insert(usedIndir.begin(), usedIndir.end());
|
||||
userDvmDirsF.push_back(distr);
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
filtered.push_back(distr);
|
||||
}
|
||||
userDvmDirs = filtered;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static void filterUserDirectives(ParallelRegion *currReg, set<string> usedArrayInRegion, vector<Statement*> userDvmDistrDirs,
|
||||
vector<Statement*> userDvmAlignDirs, vector<Statement*> userDvmShadowDirs)
|
||||
{
|
||||
vector<Statement*> userDvmDistrDirsF;
|
||||
vector<Statement*> userDvmAlignDirsF;
|
||||
vector<Statement*> userDvmShadowDirsF;
|
||||
|
||||
bool changed = false;
|
||||
do
|
||||
{
|
||||
changed = false;
|
||||
|
||||
bool ret = filterUserDirectives(usedArrayInRegion, userDvmDistrDirs, userDvmDistrDirsF);
|
||||
changed = changed || ret;
|
||||
|
||||
ret = filterUserDirectives(usedArrayInRegion, userDvmAlignDirs, userDvmAlignDirsF);
|
||||
changed = changed || ret;
|
||||
|
||||
ret = filterUserDirectives(usedArrayInRegion, userDvmShadowDirs, userDvmShadowDirsF);
|
||||
changed = changed || ret;
|
||||
|
||||
} while (changed);
|
||||
|
||||
currReg->AddUserDirectives(userDvmDistrDirsF, DVM_DISTRIBUTE_DIR);
|
||||
currReg->AddUserDirectives(userDvmAlignDirsF, DVM_ALIGN_DIR);
|
||||
currReg->AddUserDirectives(userDvmShadowDirsF, DVM_SHADOW_DIR);
|
||||
}
|
||||
|
||||
static void setExplicitFlag(const string &name, const map<string, FuncInfo*> &mapFuncs)
|
||||
{
|
||||
auto it = mapFuncs.find(name);
|
||||
if (it != mapFuncs.end())
|
||||
it->second->inRegion = 1;
|
||||
}
|
||||
|
||||
static void fillDvmDirs(SgStatement *st, vector<Statement*> &userDvmDistrDirs, vector<Statement*> &userDvmAlignDirs,
|
||||
vector<Statement*> &userDvmShadowDirs, vector<Statement*> &userDvmRealignDirs, vector<Statement*> &userDvmRedistrDirs,
|
||||
vector<Statement*>& userDvmRealignDirsDef, vector<Statement*>& userDvmRedistrDirsDef,
|
||||
const bool ®ionStarted, const map<int, LoopGraph*> &allLoopsInFile)
|
||||
{
|
||||
switch (st->variant())
|
||||
{
|
||||
case DVM_VAR_DECL:
|
||||
{
|
||||
string unparsed = st->unparse();
|
||||
convertToLower(unparsed);
|
||||
if (unparsed.find("distribute") != string::npos)
|
||||
userDvmDistrDirs.push_back(new Statement(st));
|
||||
else if (unparsed.find("align") != string::npos)
|
||||
userDvmAlignDirs.push_back(new Statement(st));
|
||||
}
|
||||
break;
|
||||
case DVM_DISTRIBUTE_DIR:
|
||||
userDvmDistrDirs.push_back(new Statement(st));
|
||||
break;
|
||||
case DVM_ALIGN_DIR:
|
||||
userDvmAlignDirs.push_back(new Statement(st));
|
||||
break;
|
||||
case DVM_SHADOW_DIR:
|
||||
userDvmShadowDirs.push_back(new Statement(st));
|
||||
break;
|
||||
case DVM_REALIGN_DIR:
|
||||
if (regionStarted)
|
||||
userDvmRealignDirs.push_back(new Statement(st));
|
||||
userDvmRealignDirsDef.push_back(new Statement(st));
|
||||
break;
|
||||
case DVM_REDISTRIBUTE_DIR:
|
||||
//skip 22.04.2020
|
||||
/*if (regionStarted)
|
||||
userDvmRedistrDirs.push_back(new Statement(st));
|
||||
userDvmRedistrDirsDef.push_back(new Statement(st));*/
|
||||
break;
|
||||
case DVM_PARALLEL_ON_DIR:
|
||||
if (st->lexNext()->variant() == FOR_NODE)
|
||||
{
|
||||
SgForStmt* forStat = (SgForStmt*)(st->lexNext());
|
||||
auto it = allLoopsInFile.find(forStat->lineNumber());
|
||||
if (it != allLoopsInFile.end())
|
||||
it->second->userDvmDirective = new Statement(st);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void checkForEmpty(SgStatement *start, SgStatement *end, vector<Messages>& messagesForFile)
|
||||
{
|
||||
bool wasStarted = false;
|
||||
int lineStarted = -1;
|
||||
|
||||
while (start != end)
|
||||
{
|
||||
if (start->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (start->variant() == SPF_PARALLEL_REG_DIR)
|
||||
{
|
||||
wasStarted = true;
|
||||
lineStarted = start->lineNumber();
|
||||
}
|
||||
else if (start->variant() == SPF_END_PARALLEL_REG_DIR)
|
||||
{
|
||||
if (wasStarted)
|
||||
{
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Empty parallel regions is forbidden.");
|
||||
__spf_printToLongBuf(messageR, R151);
|
||||
messagesForFile.push_back(Messages(ERROR, lineStarted, messageR, messageE, 3021));
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wasStarted = false;
|
||||
lineStarted = -1;
|
||||
}
|
||||
start = start->lexNext();
|
||||
}
|
||||
}
|
||||
|
||||
void fillRegionLines(SgFile *file, vector<ParallelRegion*> ®ions, vector<Messages>& messagesForFile, vector<LoopGraph*> *loops, vector<FuncInfo*> *funcs)
|
||||
{
|
||||
map<string, FuncInfo*> mapFuncs;
|
||||
if (funcs)
|
||||
createMapOfFunc(*funcs, mapFuncs);
|
||||
|
||||
//fill default
|
||||
ParallelRegion* defaultR = regions[0];
|
||||
pair<int, int> lines;
|
||||
//pair<SgStatement*, SgStatement*> startEndDef(NULL, NULL);
|
||||
{
|
||||
SgStatement* st = file->firstStatement();
|
||||
st = st->lexNext();
|
||||
lines = make_pair(st->lineNumber(), 0);
|
||||
//startEndDef.first = st;
|
||||
|
||||
while (st)
|
||||
{
|
||||
st = st->lastNodeOfStmt();
|
||||
lines.second = st->lineNumber();
|
||||
//startEndDef.second = st;
|
||||
st = st->lexNext();
|
||||
}
|
||||
}
|
||||
defaultR->AddLines(lines, file->filename());
|
||||
|
||||
map<int, LoopGraph*> allLoopsInFile;
|
||||
if (loops)
|
||||
createMapLoopGraph(allLoopsInFile, loops);
|
||||
|
||||
//fill user's
|
||||
int funcNum = file->numberOfFunctions();
|
||||
string regionName = "";
|
||||
map<string, pair<Statement*, Statement*>> startEnd;
|
||||
map<string, pair<int, int>> lines_;
|
||||
set<string> funcCallFromReg;
|
||||
bool regionStarted = false;
|
||||
|
||||
vector<SgStatement*> toDel;
|
||||
for (int i = 0; i < funcNum; ++i)
|
||||
{
|
||||
vector<Statement*> userDvmDistrDirs;
|
||||
vector<Statement*> userDvmAlignDirs;
|
||||
vector<Statement*> userDvmShadowDirs;
|
||||
vector<Statement*> userDvmRealignDirs;
|
||||
vector<Statement*> userDvmRedistrDirs;
|
||||
|
||||
vector<Statement*> userDvmRealignDirsDef;
|
||||
vector<Statement*> userDvmRedistrDirsDef;
|
||||
|
||||
set<string> usedArrayInRegion;
|
||||
|
||||
SgStatement *st = file->functions(i);
|
||||
SgStatement *lastNode = st->lastNodeOfStmt();
|
||||
|
||||
string containsPrefix = "";
|
||||
SgStatement *st_cp = st->controlParent();
|
||||
if (st_cp->variant() == PROC_HEDR || st_cp->variant() == PROG_HEDR || st_cp->variant() == FUNC_HEDR)
|
||||
containsPrefix = st_cp->symbol()->identifier() + string(".");
|
||||
const string funcName = containsPrefix + file->functions(i)->symbol()->identifier();
|
||||
|
||||
checkForEmpty(st, lastNode, messagesForFile);
|
||||
while (st != NULL && st != lastNode)
|
||||
{
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
SgStatement *prev = st->lexPrev();
|
||||
SgStatement *next = st->lexNext();
|
||||
|
||||
if (prev && prev->variant() == SPF_PARALLEL_REG_DIR)
|
||||
{
|
||||
SgStatement *data = prev;
|
||||
|
||||
regionStarted = true;
|
||||
regionName = data->symbol()->identifier();
|
||||
if (funcs)
|
||||
{
|
||||
auto itFunc = mapFuncs.find(funcName);
|
||||
if (itFunc != mapFuncs.end())
|
||||
{
|
||||
itFunc->second->inRegion = 3;
|
||||
itFunc->second->callRegions.insert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (next && next->variant() == SPF_END_PARALLEL_REG_DIR)
|
||||
{
|
||||
updateRegionInfo(st, startEnd, lines_, funcCallFromReg, mapFuncs);
|
||||
SgStatement *data = next;
|
||||
|
||||
lines.second = data->lineNumber();
|
||||
regionStarted = false;
|
||||
|
||||
if (regionName == "")
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
auto it = regionIdByName.find(regionName);
|
||||
ParallelRegion *currReg = NULL;
|
||||
if (it == regionIdByName.end())
|
||||
{
|
||||
it = regionIdByName.insert(it, make_pair(regionName, regionIdConuter));
|
||||
currReg = new ParallelRegion(regionIdConuter, regionName);
|
||||
regions.push_back(currReg);
|
||||
regionByName[regionName] = currReg;
|
||||
regionName = "";
|
||||
regionIdConuter++;
|
||||
}
|
||||
else
|
||||
currReg = regionByName[regionName];
|
||||
|
||||
if (currReg == NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
extendRegionInfo(st, startEnd, lines_, true);
|
||||
for (auto itRegInfo = startEnd.begin(); itRegInfo != startEnd.end(); ++itRegInfo)
|
||||
currReg->AddLines(lines_[itRegInfo->first], itRegInfo->first, &itRegInfo->second);
|
||||
|
||||
for (auto &func : funcCallFromReg)
|
||||
currReg->AddFuncCalls(func);
|
||||
|
||||
filterUserDirectives(currReg, usedArrayInRegion, userDvmRedistrDirs, userDvmRealignDirs, userDvmShadowDirs);
|
||||
currReg->AddUserDirectives(userDvmRealignDirs, DVM_REALIGN_DIR);
|
||||
currReg->AddUserDirectives(userDvmRedistrDirs, DVM_REDISTRIBUTE_DIR);
|
||||
|
||||
startEnd.clear();
|
||||
lines_.clear();
|
||||
funcCallFromReg.clear();
|
||||
|
||||
userDvmRealignDirs.clear();
|
||||
userDvmRedistrDirs.clear();
|
||||
|
||||
usedArrayInRegion.clear();
|
||||
}
|
||||
|
||||
|
||||
if (regionStarted)
|
||||
{
|
||||
updateRegionInfo(st, startEnd, lines_, funcCallFromReg, mapFuncs);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
fillArrayNamesInReg(usedArrayInRegion, st->expr(i));
|
||||
}
|
||||
|
||||
fillDvmDirs(st, userDvmDistrDirs, userDvmAlignDirs, userDvmShadowDirs, userDvmRealignDirs, userDvmRealignDirs, userDvmRealignDirsDef, userDvmRealignDirsDef, regionStarted, allLoopsInFile);
|
||||
if (st->variant() == DVM_SHADOW_GROUP_DIR || st->variant() == DVM_SHADOW_START_DIR || st->variant() == DVM_SHADOW_WAIT_DIR)
|
||||
toDel.push_back(st);
|
||||
st = st->lexNext();
|
||||
}
|
||||
|
||||
//for default
|
||||
defaultR->AddUserDirectives(userDvmDistrDirs, DVM_DISTRIBUTE_DIR);
|
||||
defaultR->AddUserDirectives(userDvmAlignDirs, DVM_ALIGN_DIR);
|
||||
defaultR->AddUserDirectives(userDvmShadowDirs, DVM_SHADOW_DIR);
|
||||
defaultR->AddUserDirectives(userDvmRealignDirsDef, DVM_REALIGN_DIR);
|
||||
defaultR->AddUserDirectives(userDvmRedistrDirsDef, DVM_REDISTRIBUTE_DIR);
|
||||
}
|
||||
|
||||
vector<SgStatement*> modules;
|
||||
findModulesInFile(file, modules);
|
||||
regionStarted = false;
|
||||
|
||||
for (auto& mod : modules)
|
||||
{
|
||||
vector<Statement*> userDvmDistrDirs;
|
||||
vector<Statement*> userDvmAlignDirs;
|
||||
vector<Statement*> userDvmShadowDirs;
|
||||
vector<Statement*> userDvmRealignDirs;
|
||||
vector<Statement*> userDvmRedistrDirs;
|
||||
|
||||
vector<Statement*> userDvmRealignDirsDef;
|
||||
vector<Statement*> userDvmRedistrDirsDef;
|
||||
|
||||
|
||||
for (SgStatement* st = mod->lexNext(); st; st = st->lexNext())
|
||||
{
|
||||
if (isSgExecutableStatement(st))
|
||||
break;
|
||||
fillDvmDirs(st, userDvmDistrDirs, userDvmAlignDirs, userDvmShadowDirs, userDvmRealignDirs, userDvmRealignDirs, userDvmRealignDirsDef, userDvmRealignDirsDef, regionStarted, allLoopsInFile);
|
||||
if (st->variant() == DVM_SHADOW_GROUP_DIR)
|
||||
toDel.push_back(st);
|
||||
}
|
||||
|
||||
//for default
|
||||
defaultR->AddUserDirectives(userDvmDistrDirs, DVM_DISTRIBUTE_DIR);
|
||||
defaultR->AddUserDirectives(userDvmAlignDirs, DVM_ALIGN_DIR);
|
||||
defaultR->AddUserDirectives(userDvmShadowDirs, DVM_SHADOW_DIR);
|
||||
defaultR->AddUserDirectives(userDvmRealignDirsDef, DVM_REALIGN_DIR);
|
||||
defaultR->AddUserDirectives(userDvmRedistrDirsDef, DVM_REDISTRIBUTE_DIR);
|
||||
}
|
||||
|
||||
for (auto& elem : toDel)
|
||||
elem->deleteStmt();
|
||||
}
|
||||
|
||||
static void getAllLoops(vector<LoopGraph*> &loopGraph, vector<LoopGraph*> &loops)
|
||||
{
|
||||
for (auto &elem : loopGraph)
|
||||
loops.push_back(elem);
|
||||
|
||||
for (auto &elem : loopGraph)
|
||||
getAllLoops(elem->children, loops);
|
||||
}
|
||||
|
||||
void fillRegionLinesStep2(vector<ParallelRegion*> ®ions, const map<string, vector<FuncInfo*>> &allFuncInfo, map<string, vector<LoopGraph*>> *loopGraph)
|
||||
{
|
||||
map<string, FuncInfo*> funcMap;
|
||||
createMapOfFunc(allFuncInfo, funcMap);
|
||||
|
||||
for (int i = 0; i < regions.size(); ++i)
|
||||
{
|
||||
if (regions[i]->GetName() != "DEFAULT")
|
||||
for (auto &func : regions[i]->GetFuncCalls())
|
||||
setExplicitFlag(func, funcMap);
|
||||
}
|
||||
|
||||
for (int i = 0; i < regions.size(); ++i)
|
||||
{
|
||||
if (regions[i]->GetName() != "DEFAULT")
|
||||
{
|
||||
set<string> uniqFuncCalls;
|
||||
for (auto &elem : regions[i]->GetFuncCalls())
|
||||
uniqFuncCalls.insert(elem);
|
||||
|
||||
bool wasChanged = 1;
|
||||
while (wasChanged)
|
||||
{
|
||||
wasChanged = 0;
|
||||
for (auto &uniqF : uniqFuncCalls)
|
||||
{
|
||||
auto func = funcMap.find(uniqF);
|
||||
if (func != funcMap.end())
|
||||
{
|
||||
for (auto &calls : func->second->callsFrom)
|
||||
{
|
||||
auto it = uniqFuncCalls.find(calls);
|
||||
if (it == uniqFuncCalls.end())
|
||||
{
|
||||
uniqFuncCalls.insert(it, calls);
|
||||
wasChanged = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string toPrint = "";
|
||||
for (auto &elem : uniqFuncCalls)
|
||||
{
|
||||
auto it = funcMap.find(elem);
|
||||
if (it != funcMap.end())
|
||||
{
|
||||
regions[i]->AddLines(it->second->linesNum, it->second->fileName);
|
||||
regions[i]->AddFuncCallsToAllCalls(it->second);
|
||||
|
||||
if (it->second->inRegion == 0)
|
||||
it->second->inRegion = 2;
|
||||
|
||||
it->second->callRegions.insert(i);
|
||||
|
||||
toPrint += elem + " ";
|
||||
}
|
||||
}
|
||||
|
||||
if (toPrint != "")
|
||||
__spf_print(1, "[%s]: funcs: %s\n", regions[i]->GetName().c_str(), toPrint.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// remove default region if user's found
|
||||
if (regions.size() > 1)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
removeFromCollection(regions[0]);
|
||||
#endif
|
||||
delete regions[0];
|
||||
regions.erase(regions.begin());
|
||||
}
|
||||
|
||||
bool changed = true;
|
||||
while (changed)
|
||||
{
|
||||
changed = false;
|
||||
for (auto &func : funcMap)
|
||||
{
|
||||
if (func.second->inRegion != 0)
|
||||
continue;
|
||||
|
||||
for (auto &callsFrom : func.second->callsFrom)
|
||||
{
|
||||
auto it = funcMap.find(callsFrom);
|
||||
if (it != funcMap.end())
|
||||
{
|
||||
if (it->second->inRegion > 0)
|
||||
{
|
||||
func.second->inRegion = 3;
|
||||
func.second->callRegions.insert(0);
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
func.second->callRegions.insert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loopGraph)
|
||||
{
|
||||
//fill regions for loop
|
||||
vector<LoopGraph*> loops;
|
||||
for (auto loop : *loopGraph)
|
||||
getAllLoops(loop.second, loops);
|
||||
|
||||
for (auto &loop : loops)
|
||||
{
|
||||
const int currLine = loop->lineNum < -1 ? loop->loop->localLineNumber() : loop->lineNum;
|
||||
set<ParallelRegion*> allRegs = getAllRegionsByLine(regions, loop->fileName, currLine);
|
||||
if (allRegs.size() == 1)
|
||||
loop->region = *(allRegs.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int printParalleRegions(const char *fileName, vector<ParallelRegion*> ®ions)
|
||||
{
|
||||
FILE *file = fopen(fileName, "w");
|
||||
if (file == NULL)
|
||||
{
|
||||
__spf_print(1, "can not open file %s\n", fileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int num = 0;
|
||||
for (auto &elem : regions)
|
||||
{
|
||||
fprintf(file, "*** #%d Parallel Region\n", num);
|
||||
elem->print(file);
|
||||
fprintf(file, "\n");
|
||||
++num;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getIntVal(SgExpression *ex)
|
||||
{
|
||||
SgExpression* calc = CalculateInteger(ex->copyPtr());
|
||||
if (calc->variant() == INT_VAL)
|
||||
return calc->valueInteger();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fillMultOp(SgExpression *ex, pair<string, pair<int, int>> &retVal)
|
||||
{
|
||||
const int var = ex->lhs()->variant();
|
||||
if (var == INT_VAL || var == CONST_REF || var == MINUS_OP) // -+a * X
|
||||
{
|
||||
retVal.first = ex->rhs()->symbol()->identifier();
|
||||
retVal.second.first = getIntVal(ex->lhs());
|
||||
}
|
||||
else if (var == VAR_REF) // X * -+a
|
||||
{
|
||||
retVal.first = ex->lhs()->symbol()->identifier();
|
||||
retVal.second.first = getIntVal(ex->rhs());
|
||||
}
|
||||
}
|
||||
|
||||
static pair<string, pair<int, int>> parseExpression(SgExpression *ex)
|
||||
{
|
||||
pair<string, pair<int, int>> retVal;
|
||||
|
||||
if (ex)
|
||||
{
|
||||
if (ex->variant() == VAR_REF)
|
||||
{
|
||||
retVal.first = ex->symbol()->identifier();
|
||||
retVal.second = make_pair(1, 0);
|
||||
}
|
||||
else if (ex->variant() == MULT_OP) // a * X
|
||||
fillMultOp(ex, retVal);
|
||||
else if (ex->variant() == ADD_OP || ex->variant() == SUBT_OP) // a * X +- b
|
||||
{
|
||||
int minus = (ex->variant() == ADD_OP) ? 1 : -1;
|
||||
if (ex->lhs()->variant() == MULT_OP) // a * X +- b
|
||||
{
|
||||
fillMultOp(ex->lhs(), retVal);
|
||||
retVal.second.second = getIntVal(ex->rhs()) * minus;
|
||||
}
|
||||
else if (ex->lhs()->variant() == INT_VAL) // b +- [a *] X
|
||||
{
|
||||
if (ex->rhs()->variant() == MULT_OP)
|
||||
fillMultOp(ex->rhs(), retVal);
|
||||
else
|
||||
{
|
||||
retVal.first = ex->rhs()->symbol()->identifier();
|
||||
retVal.second.first = minus;
|
||||
}
|
||||
retVal.second.second = getIntVal(ex->lhs()) * minus;
|
||||
}
|
||||
else if (ex->lhs()->variant() == VAR_REF && ex->rhs()->variant()) // X +- b
|
||||
{
|
||||
retVal.first = ex->lhs()->symbol()->identifier();
|
||||
retVal.second.first = 1;
|
||||
retVal.second.second = getIntVal(ex->rhs()) * minus;
|
||||
}
|
||||
else
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
else if (ex->variant() == KEYWORD_VAL) // *
|
||||
{
|
||||
SgKeywordValExp* keyVal = (SgKeywordValExp*)ex;
|
||||
if (keyVal->value())
|
||||
retVal = make_pair(keyVal->value(), make_pair(0, 0));
|
||||
}
|
||||
else if (ex->variant() == DDOT || ex->variant() == INT_VAL || ex->variant() == CONST_REF) // ':' | 'digit' equal '*'
|
||||
retVal = make_pair("*", make_pair(0, 0));
|
||||
else
|
||||
{
|
||||
__spf_print(1, "align pattern: '%s'\n", ex->unparse());
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static void fillTemplate(SgExpression *ex, vector<pair<string, pair<int, int>>> &templateArray)
|
||||
{
|
||||
for (SgExpression *list = ex; list; list = list->rhs())
|
||||
templateArray.push_back(parseExpression(list->lhs()));
|
||||
}
|
||||
|
||||
static int getTemplateDemention(const string &val, const vector<pair<string, pair<int, int>>> &alignWithTemplate)
|
||||
{
|
||||
int ret = -1;
|
||||
for (int k = 0; k < alignWithTemplate.size(); ++k)
|
||||
{
|
||||
if (alignWithTemplate[k].first == val)
|
||||
{
|
||||
ret = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool needToSkip(SgStatement* dir, vector<FuncInfo*> funcs)
|
||||
{
|
||||
bool retVal = false;
|
||||
|
||||
auto iterator = dir;
|
||||
|
||||
while (iterator && iterator->variant() != PROG_HEDR && iterator->variant() != PROC_HEDR && iterator->variant() != FUNC_HEDR)
|
||||
iterator = iterator->controlParent();
|
||||
|
||||
if (iterator == NULL)
|
||||
return retVal;
|
||||
|
||||
for (auto& elem : funcs)
|
||||
{
|
||||
if (elem->funcPointer->GetOriginal()->thebif == iterator->thebif)
|
||||
{
|
||||
if (elem->doNotAnalyze)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool buildGraphFromUserDirectives(const vector<Statement*> &userDvmAlignDirs, DIST::GraphCSR<int, double, attrType> &G,
|
||||
DIST::Arrays<int> &allArrays, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
|
||||
const set<DIST::Array*>& alignedArrays, set<DIST::Array*>& addedArrays,
|
||||
const map<string, vector<FuncInfo*>>& funcsByFile)
|
||||
{
|
||||
if (userDvmAlignDirs.size())
|
||||
{
|
||||
bool cleaned = false;
|
||||
|
||||
int t = 0;
|
||||
for (auto &dir : userDvmAlignDirs)
|
||||
{
|
||||
const string file = dir->GetFileNameIncludedTo();
|
||||
if (SgFile::switchToFile(file) == -1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
auto it = funcsByFile.find(file);
|
||||
|
||||
if (needToSkip(dir->GetOriginal(), it == funcsByFile.end() ? vector<FuncInfo*>() : it->second));
|
||||
continue;
|
||||
|
||||
vector<DIST::Array*> alignArrays;
|
||||
|
||||
vector<pair<string, pair<int, int>>> alignTemplate;
|
||||
|
||||
DIST::Array* alignWithArray = NULL;
|
||||
vector<pair<string, pair<int, int>>> alignWithTemplate;
|
||||
|
||||
if (dir->expr(0) == NULL)
|
||||
return true;
|
||||
|
||||
for (SgExpression *ex = dir->expr(0); ex; ex = ex->rhs())
|
||||
{
|
||||
SgExpression *val = ex->lhs();
|
||||
if (val->variant() == ARRAY_REF && val->symbol())
|
||||
{
|
||||
DIST::Array *newValue = getArrayFromDeclarated(declaratedInStmt(val->symbol()), val->symbol()->identifier());
|
||||
if (newValue)
|
||||
alignArrays.push_back(newValue);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
map<DIST::Array*, set<DIST::Array*>> realAlignArrayRefs;
|
||||
for (auto &access : alignArrays)
|
||||
getRealArrayRefs(access, access, realAlignArrayRefs[access], arrayLinksByFuncCalls);
|
||||
|
||||
set<DIST::Array*> realAlignArrayRefsSet;
|
||||
for (auto &elem : realAlignArrayRefs)
|
||||
realAlignArrayRefsSet.insert(elem.second.begin(), elem.second.end());
|
||||
|
||||
if (dir->expr(1))
|
||||
fillTemplate(dir->expr(1), alignTemplate);
|
||||
else if (dir->variant() == DVM_VAR_DECL)
|
||||
fillTemplate(dir->expr(2)->lhs()->lhs(), alignTemplate);
|
||||
else
|
||||
return true;
|
||||
|
||||
if (dir->expr(2))
|
||||
{
|
||||
SgExpression *ex = dir->expr(2);
|
||||
if (ex->variant() == EXPR_LIST && ex->lhs()->variant() == ALIGN_OP)
|
||||
ex = ex->lhs()->rhs();
|
||||
|
||||
if (ex && ex->variant() == ARRAY_REF && ex->symbol())
|
||||
{
|
||||
alignWithArray = getArrayFromDeclarated(declaratedInStmt(ex->symbol()), ex->symbol()->identifier());
|
||||
if (alignWithArray == NULL)
|
||||
return true;
|
||||
fillTemplate(ex->lhs(), alignWithTemplate);
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
|
||||
string tmp;
|
||||
for (auto& elem : realAlignArrayRefsSet)
|
||||
tmp += elem->GetName() + " ";
|
||||
__spf_print(1, " align array%s '%s' from user dir in line %d\n", (realAlignArrayRefsSet.size() == 1 ? "" : "s"), tmp.c_str(), dir->lineNumber());
|
||||
__spf_print(1, " template align:\n");
|
||||
for (int i = 0; i < alignTemplate.size(); ++i)
|
||||
__spf_print(1, " -- %d: %s -- [%d, %d]\n", i, alignTemplate[i].first.c_str(), alignTemplate[i].second.first, alignTemplate[i].second.second);
|
||||
__spf_print(1, " template align with:\n");
|
||||
for (int i = 0; i < alignWithTemplate.size(); ++i)
|
||||
__spf_print(1, " -- %d: %s -- [%d, %d]\n", i, alignWithTemplate[i].first.c_str(), alignWithTemplate[i].second.first, alignWithTemplate[i].second.second);
|
||||
|
||||
for (int i = 0; i < alignTemplate.size(); ++i)
|
||||
{
|
||||
if (alignTemplate[i].first != "*")
|
||||
{
|
||||
int dimT = getTemplateDemention(alignTemplate[i].first, alignWithTemplate);
|
||||
if (dimT == -1)
|
||||
continue;
|
||||
|
||||
for (auto& array : realAlignArrayRefsSet)
|
||||
{
|
||||
if (!array->IsNotDistribute())
|
||||
{
|
||||
if (alignWithArray->IsTemplate() && alignWithArray->GetShortName().find("_r") != string::npos)
|
||||
continue;
|
||||
|
||||
//TODO:
|
||||
/*if (alignedArrays.find(array) != alignedArrays.end())
|
||||
continue;*/
|
||||
addedArrays.insert(array);
|
||||
|
||||
if (!cleaned)
|
||||
{
|
||||
cleaned = true;
|
||||
G.ClearGraphCSR();
|
||||
}
|
||||
|
||||
DIST::AddArrayAccess(G, allArrays, array, alignWithArray, make_pair(i, dimT), 1.0, make_pair(make_pair(1, 0), alignWithTemplate[dimT].second), WW_link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void calculateLinesOfCode(vector<ParallelRegion*> &allRegions)
|
||||
{
|
||||
for (auto &elem : allRegions)
|
||||
{
|
||||
auto allLines = elem->GetAllLines();
|
||||
int lineCounter = 0;
|
||||
for (auto &line : allLines)
|
||||
for (auto &lineV : line.second)
|
||||
lineCounter += (lineV.lines.second - lineV.lines.first);
|
||||
|
||||
__spf_print(1, " Count of lines in region '%s' = %d\n", elem->GetName().c_str(), lineCounter);
|
||||
}
|
||||
}
|
||||
402
Sapfor/_src/ParallelizationRegions/ParRegions.h
Normal file
402
Sapfor/_src/ParallelizationRegions/ParRegions.h
Normal file
@@ -0,0 +1,402 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "../Distribution/DvmhDirective.h"
|
||||
#include "../Distribution/GraphCSR.h"
|
||||
#include "../Distribution/Distribution.h"
|
||||
#include "../Utils/AstWrapper.h"
|
||||
|
||||
#if __SPF
|
||||
#include "../Utils/SgUtils.h"
|
||||
#endif
|
||||
|
||||
struct ParallelRegionLines
|
||||
{
|
||||
ParallelRegionLines()
|
||||
{
|
||||
lines = std::make_pair(-1, -1);
|
||||
stats = std::make_pair<Statement*, Statement*>(NULL, NULL);
|
||||
intervalBefore = std::make_pair<Statement*, Statement*>(NULL, NULL);
|
||||
intervalAfter = std::make_pair<Statement*, Statement*>(NULL, NULL);
|
||||
}
|
||||
|
||||
ParallelRegionLines(const std::pair<int, int> &lines) : lines(lines)
|
||||
{
|
||||
stats = std::make_pair<Statement*, Statement*>(NULL, NULL);
|
||||
intervalBefore = std::make_pair<Statement*, Statement*>(NULL, NULL);
|
||||
intervalAfter = std::make_pair<Statement*, Statement*>(NULL, NULL);
|
||||
}
|
||||
|
||||
ParallelRegionLines(const std::pair<int, int> &lines, const std::pair<Statement*, Statement*> stats) : lines(lines), stats(stats)
|
||||
{
|
||||
intervalBefore = std::make_pair<Statement*, Statement*>(NULL, NULL);
|
||||
intervalAfter = std::make_pair<Statement*, Statement*>(NULL, NULL);
|
||||
}
|
||||
|
||||
bool operator==(const ParallelRegionLines ®ionLines) const { return lines == regionLines.lines && stats == regionLines.stats; }
|
||||
bool operator<(const ParallelRegionLines &otherLines) const { return lines.first < otherLines.lines.first; }
|
||||
|
||||
void print(FILE *fileOut)
|
||||
{
|
||||
fprintf(fileOut, " [%d -- %d]", lines.first, lines.second);
|
||||
if (stats.first && stats.second)
|
||||
fprintf(fileOut, " explicit\n");
|
||||
else
|
||||
fprintf(fileOut, "\n");
|
||||
}
|
||||
|
||||
bool isImplicit() const { return stats.first == NULL || stats.second == NULL; }
|
||||
|
||||
// <start, end> lines
|
||||
std::pair<int, int> lines;
|
||||
// <start, end> stats
|
||||
std::pair<Statement*, Statement*> stats;
|
||||
|
||||
// <start, end> interval
|
||||
std::pair<Statement*, Statement*> intervalBefore;
|
||||
std::pair<Statement*, Statement*> intervalAfter;
|
||||
};
|
||||
|
||||
#if __SPF
|
||||
struct ParallelRegionArray
|
||||
{
|
||||
private:
|
||||
std::string name;
|
||||
std::string fileName;
|
||||
SgSymbol *origSymbol;
|
||||
SgSymbol *copySymbol;
|
||||
std::vector<SgStatement*> declStatements;
|
||||
std::vector<ParallelRegionLines> allLines;
|
||||
public:
|
||||
explicit ParallelRegionArray(const std::string &name, const std::string &fileName, SgSymbol *origSymbol, SgSymbol *copySymbol,
|
||||
const ParallelRegionLines &lines, std::vector<SgStatement*> &declStatements) :
|
||||
name(name), fileName(fileName), origSymbol(origSymbol), copySymbol(copySymbol), declStatements(declStatements)
|
||||
{
|
||||
allLines.push_back(lines);
|
||||
}
|
||||
|
||||
const std::string& getName() const { return name; }
|
||||
const std::string& getFileName() const { return fileName; }
|
||||
SgSymbol* getOrigSymbol() const { return origSymbol; }
|
||||
SgSymbol* getCopySymbol() const { return copySymbol; }
|
||||
const std::vector<SgStatement*>& getDeclStatements() const { return declStatements; }
|
||||
const std::vector<ParallelRegionLines>& getAllLines() const { return allLines; }
|
||||
|
||||
void addLines(const ParallelRegionLines &newLines)
|
||||
{
|
||||
for (auto &lines : allLines)
|
||||
if (lines == newLines)
|
||||
return;
|
||||
|
||||
allLines.push_back(newLines);
|
||||
}
|
||||
|
||||
void setCopySymbol(SgSymbol *copySymbol) { this->copySymbol = copySymbol; }
|
||||
};
|
||||
#endif
|
||||
|
||||
struct ParallelRegion
|
||||
{
|
||||
public:
|
||||
ParallelRegion(const uint64_t regionId, const std::string &originalName) : regionId(regionId), originalName(originalName) { }
|
||||
|
||||
ParallelRegion(const ParallelRegion ©) : allArrays(copy.allArrays), G(copy.G), reducedG(copy.reducedG), dataDirectives(copy.dataDirectives)
|
||||
{
|
||||
regionId = copy.regionId;
|
||||
originalName = copy.originalName;
|
||||
lines = copy.lines;
|
||||
functionsCall = copy.functionsCall;
|
||||
currentVariant = copy.currentVariant;
|
||||
}
|
||||
|
||||
int AddLines(const std::pair<int, int> &linesToAdd, const std::string &file, const std::pair<Statement*, Statement*> *startEnd = NULL)
|
||||
{
|
||||
if (linesToAdd.first > linesToAdd.second)
|
||||
return -1;
|
||||
|
||||
auto it = lines.find(file);
|
||||
if (it == lines.end())
|
||||
it = lines.insert(it, make_pair(file, std::vector<ParallelRegionLines>()));
|
||||
|
||||
if (startEnd)
|
||||
it->second.push_back(ParallelRegionLines(linesToAdd, *startEnd));
|
||||
else
|
||||
it->second.push_back(ParallelRegionLines(linesToAdd));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AddFuncCalls(const std::string &func) { functionsCall.insert(func); }
|
||||
|
||||
#if __SPF
|
||||
void AddFuncCallsToAllCalls(FuncInfo *func) { allFunctionsCall.insert(func); }
|
||||
#endif
|
||||
|
||||
uint64_t GetId() const { return regionId; }
|
||||
const std::string& GetName() const { return originalName; }
|
||||
const std::map<std::string, std::vector<ParallelRegionLines>>& GetAllLines() const { return lines; }
|
||||
std::map<std::string, std::vector<ParallelRegionLines>>& GetAllLinesToModify() { return lines; }
|
||||
const std::vector<ParallelRegionLines>* GetLines(const std::string &file) const
|
||||
{
|
||||
auto it = lines.find(file);
|
||||
if (it == lines.end())
|
||||
return NULL;
|
||||
else
|
||||
return &(it->second);
|
||||
}
|
||||
const ParallelRegionLines* GetLinesByLine(const std::string &file, const int line) const
|
||||
{
|
||||
auto fileLines = GetLines(file);
|
||||
if (fileLines)
|
||||
for (auto &lines : *fileLines)
|
||||
if (lines.lines.first <= line && line <= lines.lines.second)
|
||||
return &lines;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const DIST::GraphCSR<int, double, attrType>& GetGraph() const { return G; }
|
||||
DIST::GraphCSR<int, double, attrType>& GetGraphToModify() { return G; }
|
||||
|
||||
const DIST::GraphCSR<int, double, attrType>& GetReducedGraph() const { return reducedG; }
|
||||
DIST::GraphCSR<int, double, attrType>& GetReducedGraphToModify() { return reducedG; }
|
||||
|
||||
const DIST::Arrays<int>& GetAllArrays() const { return allArrays; }
|
||||
DIST::Arrays<int>& GetAllArraysToModify() { return allArrays; }
|
||||
|
||||
void SetCurrentVariant(const std::vector<int> &newVariant) { currentVariant = newVariant; }
|
||||
const std::vector<int>& GetCurrentVariant() const { return currentVariant; }
|
||||
|
||||
const DataDirective& GetDataDir() const { return dataDirectives; }
|
||||
DataDirective& GetDataDirToModify() { return dataDirectives; }
|
||||
|
||||
const std::set<std::string>& GetFuncCalls() const { return functionsCall; }
|
||||
|
||||
#if __SPF
|
||||
const std::set<FuncInfo*>& GetAllFuncCalls() const { return allFunctionsCall; }
|
||||
const std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>>& GetUsedLocalArrays() const { return usedLocalArrays; }
|
||||
const std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>>& GetUsedCommonArrays() const { return usedCommonArrays; }
|
||||
|
||||
void AddUsedLocalArray(FuncInfo *func, DIST::Array *array, const ParallelRegionLines &lines)
|
||||
{
|
||||
auto it = usedLocalArrays.find(func);
|
||||
if (it == usedLocalArrays.end())
|
||||
it = usedLocalArrays.insert(it, std::make_pair(func, std::map<DIST::Array*, std::vector<ParallelRegionLines>>()));
|
||||
|
||||
auto itt = it->second.find(array);
|
||||
if (itt == it->second.end())
|
||||
itt = it->second.insert(itt, std::make_pair(array, std::vector<ParallelRegionLines>()));
|
||||
|
||||
for (auto &curLines : itt->second)
|
||||
if (curLines == lines)
|
||||
return;
|
||||
|
||||
itt->second.push_back(lines);
|
||||
}
|
||||
|
||||
void AddUsedCommonArray(FuncInfo *func, DIST::Array *array, const ParallelRegionLines &lines)
|
||||
{
|
||||
auto it = usedCommonArrays.find(func);
|
||||
if (it == usedCommonArrays.end())
|
||||
it = usedCommonArrays.insert(it, std::make_pair(func, std::map<DIST::Array*, std::vector<ParallelRegionLines>>()));
|
||||
|
||||
auto itt = it->second.find(array);
|
||||
if (itt == it->second.end())
|
||||
itt = it->second.insert(itt, std::make_pair(array, std::vector<ParallelRegionLines>()));
|
||||
|
||||
for (auto &curLines : itt->second)
|
||||
if (curLines == lines)
|
||||
return;
|
||||
|
||||
itt->second.push_back(lines);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool HasThisLine(const int line, const std::string &file) const
|
||||
{
|
||||
bool retVal = false;
|
||||
auto it = lines.find(file);
|
||||
if (it != lines.end())
|
||||
{
|
||||
for (int i = 0; i < it->second.size(); ++i)
|
||||
{
|
||||
if (it->second[i].lines.first <= line && it->second[i].lines.second >= line)
|
||||
{
|
||||
retVal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
std::string toString()
|
||||
{
|
||||
std::string retVal = "";
|
||||
|
||||
retVal += "#" + std::to_string(regionId);
|
||||
retVal += "#" + originalName;
|
||||
retVal += "#" + std::to_string(lines.size());
|
||||
|
||||
for (auto it = lines.begin(); it != lines.end(); ++it)
|
||||
{
|
||||
retVal += "|" + it->first + "|";
|
||||
retVal += std::to_string(it->second.size());
|
||||
for (int i = 0; i < it->second.size(); ++i)
|
||||
retVal += "#" + std::to_string(it->second[i].lines.first) + "#" + std::to_string(it->second[i].lines.second);
|
||||
}
|
||||
|
||||
const std::set<DIST::Array*> &arrays = allArrays.GetArrays();
|
||||
retVal += "#" + std::to_string(arrays.size());
|
||||
|
||||
//create map<array_address, DIST::Array_toString()>
|
||||
for (auto it = arrays.begin(); it != arrays.end(); ++it)
|
||||
{
|
||||
retVal += "#" + std::to_string((long long)(*it));
|
||||
retVal += "#" + (*it)->toString();
|
||||
}
|
||||
|
||||
retVal += "#" + std::to_string(dataDirectives.alignRules.size());
|
||||
for (int i = 0; i < dataDirectives.alignRules.size(); ++i)
|
||||
retVal += dataDirectives.alignRules[i].toString();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void CleanData()
|
||||
{
|
||||
reducedG.ClearGraphCSR();
|
||||
currentVariant.clear();
|
||||
|
||||
dataDirectives.distrRules.clear();
|
||||
dataDirectives.alignRules.clear();
|
||||
}
|
||||
|
||||
void print(FILE *fileOut)
|
||||
{
|
||||
fprintf(fileOut, " regionId %lld\n", regionId);
|
||||
fprintf(fileOut, " originalName '%s'\n", originalName.c_str());
|
||||
fprintf(fileOut, " functions call from %d:\n", (int)functionsCall.size());
|
||||
for (auto &func : functionsCall)
|
||||
fprintf(fileOut, " '%s'\n", func.c_str());
|
||||
fprintf(fileOut, " total lines %d:\n", (int)lines.size());
|
||||
for (auto &line : lines)
|
||||
{
|
||||
fprintf(fileOut, " in file '%s':\n", line.first.c_str());
|
||||
for (auto &elem : line.second)
|
||||
{
|
||||
fprintf(fileOut, " ");
|
||||
elem.print(fileOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddUserDirectives(const std::vector<Statement*> &dirs, const int type)
|
||||
{
|
||||
if (dirs.size() == 0)
|
||||
return;
|
||||
|
||||
if (type == DVM_DISTRIBUTE_DIR || type == DVM_VAR_DECL)
|
||||
userDvmDistrDirs.insert(userDvmDistrDirs.end(), dirs.begin(), dirs.end());
|
||||
else if (type == DVM_ALIGN_DIR)
|
||||
userDvmAlignDirs.insert(userDvmAlignDirs.end(), dirs.begin(), dirs.end());
|
||||
else if (type == DVM_SHADOW_DIR)
|
||||
userDvmShadowDirs.insert(userDvmShadowDirs.end(), dirs.begin(), dirs.end());
|
||||
else if (type == DVM_REALIGN_DIR)
|
||||
userDvmRealignDirs.insert(userDvmRealignDirs.end(), dirs.begin(), dirs.end());
|
||||
else if (type == DVM_REDISTRIBUTE_DIR)
|
||||
userDvmRedistrDirs.insert(userDvmRedistrDirs.end(), dirs.begin(), dirs.end());
|
||||
}
|
||||
|
||||
const std::vector<Statement*>* GetUsersDirecites(const int type) const
|
||||
{
|
||||
if (type == DVM_DISTRIBUTE_DIR || type == DVM_VAR_DECL)
|
||||
return &userDvmDistrDirs;
|
||||
else if (type == DVM_ALIGN_DIR)
|
||||
return &userDvmAlignDirs;
|
||||
else if (type == DVM_SHADOW_DIR)
|
||||
return &userDvmShadowDirs;
|
||||
else if (type == DVM_REALIGN_DIR)
|
||||
return &userDvmRealignDirs;
|
||||
else if (type == DVM_REDISTRIBUTE_DIR)
|
||||
return &userDvmRedistrDirs;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool HasUserDvmDirs() const
|
||||
{
|
||||
return userDvmDistrDirs.size() != 0 ||
|
||||
userDvmAlignDirs.size() != 0 ||
|
||||
userDvmShadowDirs.size() != 0 ||
|
||||
userDvmRealignDirs.size() != 0 ||
|
||||
userDvmRedistrDirs.size() != 0;
|
||||
}
|
||||
#if __SPF
|
||||
void ClearUserDirs()
|
||||
{
|
||||
ClearVector(userDvmDistrDirs);
|
||||
ClearVector(userDvmAlignDirs);
|
||||
ClearVector(userDvmShadowDirs);
|
||||
ClearVector(userDvmRealignDirs);
|
||||
ClearVector(userDvmRedistrDirs);
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
uint64_t regionId;
|
||||
//name in program
|
||||
std::string originalName;
|
||||
// file -> lines info
|
||||
std::map<std::string, std::vector<ParallelRegionLines>> lines;
|
||||
std::set<std::string> functionsCall;
|
||||
|
||||
#if __SPF
|
||||
// for RESOLVE_PAR_REGIONS
|
||||
std::set<FuncInfo*> allFunctionsCall;
|
||||
std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>> usedLocalArrays; // func -> array -> lines
|
||||
std::map<FuncInfo*, std::map<DIST::Array*, std::vector<ParallelRegionLines>>> usedCommonArrays; // func -> array -> lines
|
||||
//
|
||||
#endif
|
||||
|
||||
// for LOOP_ANALYZER_DATA_DIST
|
||||
DIST::GraphCSR<int, double, attrType> G;
|
||||
DIST::Arrays<int> allArrays;
|
||||
|
||||
DIST::GraphCSR<int, double, attrType> reducedG;
|
||||
//
|
||||
|
||||
//for directive creating
|
||||
DataDirective dataDirectives;
|
||||
std::vector<int> currentVariant;
|
||||
//
|
||||
|
||||
std::vector<Statement*> userDvmDistrDirs;
|
||||
std::vector<Statement*> userDvmAlignDirs;
|
||||
std::vector<Statement*> userDvmShadowDirs;
|
||||
std::vector<Statement*> userDvmRealignDirs;
|
||||
std::vector<Statement*> userDvmRedistrDirs;
|
||||
|
||||
#if __SPF
|
||||
void ClearVector(std::vector<Statement*> &toRem)
|
||||
{
|
||||
for (auto& elem : toRem)
|
||||
{
|
||||
if (SgFile::switchToFile(elem->fileName()))
|
||||
;// printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
else
|
||||
elem->deleteStmt();
|
||||
}
|
||||
toRem.clear();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
ParallelRegion* getRegionById(const std::vector<ParallelRegion*>& regions, const uint64_t regionId);
|
||||
ParallelRegion* getRegionByName(const std::vector<ParallelRegion*>& regions, const std::string& regionName);
|
||||
ParallelRegion* getRegionByLine(const std::vector<ParallelRegion*>& regions, const std::string& file, const int line);
|
||||
std::set<ParallelRegion*> getAllRegionsByLine(const std::vector<ParallelRegion*>& regions, const std::string& file, const int line);
|
||||
12
Sapfor/_src/ParallelizationRegions/ParRegions_func.h
Normal file
12
Sapfor/_src/ParallelizationRegions/ParRegions_func.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "ParRegions.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
|
||||
void fillRegionLines(SgFile *file, std::vector<ParallelRegion*> ®ions, std::vector<Messages>& messagesForFile, std::vector<LoopGraph*> *loops = NULL, std::vector<FuncInfo*> *funcs = NULL);
|
||||
void fillRegionLinesStep2(std::vector<ParallelRegion*> ®ions, const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo, std::map<std::string, std::vector<LoopGraph*>> *loopGraph = NULL);
|
||||
int printParalleRegions(const char *fileName, std::vector<ParallelRegion*> ®ions);
|
||||
bool buildGraphFromUserDirectives(const std::vector<Statement*> &userDvmAlignDirs, DIST::GraphCSR<int, double, attrType> &G, DIST::Arrays<int> &allArrays, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, const std::set<DIST::Array*>& alignedArrays, std::set<DIST::Array*>& addedArrays, const std::map<std::string, std::vector<FuncInfo*>>& funcsByFile);
|
||||
void clearRegionStaticData();
|
||||
void calculateLinesOfCode(std::vector<ParallelRegion*> &allRegions);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user