From d46befda364790de61c7ed70cdde20b8958e87b0 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 1 Aug 2018 15:17:06 +0200 Subject: [PATCH 01/85] build generate_isl_cpp_h unconditionally In particular, also build this target when WITH_BINDINGS is not set. In this case, it currently does nothing and does not depend on anything, but the availability of an unconditional target will make it possible to reuse this target to also build the templated isl header in the next commit, independently of the WITH_BINDINGS setting. --- CMakeLists.txt | 10 ++++++++++ isl_interface/CMakeLists.txt | 6 ++---- tc/core/CMakeLists.txt | 4 +--- test/CMakeLists.txt | 4 +--- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2dd1d46e0..30a6e721c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -334,6 +334,16 @@ else() message(STATUS "Not building benchmarks, caffe2 or CUDA not available") endif() +SET(ISL_CPP_H "${CMAKE_CURRENT_LIST_DIR}/isl_interface/include/isl/cpp.h") + if (WITH_BINDINGS) add_subdirectory(isl_interface) + + # generate_isl_cpp_h is the dependency that should be used + # by code that depends on the isl C++ bindings. + add_custom_target(generate_isl_cpp_h + DEPENDS generate_isl_cpp_h_core) +else() + add_custom_target(generate_isl_cpp_h + DEPENDS) endif() diff --git a/isl_interface/CMakeLists.txt b/isl_interface/CMakeLists.txt index 6ddb04b75..e710e93f9 100644 --- a/isl_interface/CMakeLists.txt +++ b/isl_interface/CMakeLists.txt @@ -87,7 +87,6 @@ target_link_libraries(extract_isl_interface # Dummy library to ensure that C++ bindings depend on contents of header files. add_library(isl_all_h_dep STATIC ${ISL_DIR}/all.c) -SET(ISL_CPP_H "${CMAKE_CURRENT_LIST_DIR}/include/isl/cpp.h") add_custom_command( OUTPUT ${ISL_CPP_H} DEPENDS isl_all_h_dep @@ -107,6 +106,5 @@ add_custom_command( COMMAND cat ${ISL_DIR}/cpp/cpp.h.bot >> ${ISL_CPP_H} || exit 1 DEPENDS extract_isl_interface ) -# generate_isl_cpp_h is the dependency that should be used -# by code that depends on the isl C++ bindings. -add_custom_target(generate_isl_cpp_h DEPENDS ${ISL_CPP_H}) + +add_custom_target(generate_isl_cpp_h_core DEPENDS ${ISL_CPP_H}) diff --git a/tc/core/CMakeLists.txt b/tc/core/CMakeLists.txt index 504dea4e6..8842ff7cf 100644 --- a/tc/core/CMakeLists.txt +++ b/tc/core/CMakeLists.txt @@ -51,9 +51,7 @@ target_link_libraries( tc_version tc_proto ) -if (WITH_BINDINGS) - add_dependencies(tc_core generate_isl_cpp_h) -endif() +add_dependencies(tc_core generate_isl_cpp_h) install( TARGETS tc_core diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5f18be9c6..f97eeb01f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,9 +13,7 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) add_executable(test_basic test_basic.cc) add_test(test_basic test_basic) target_link_libraries(test_basic ${GOOGLE_LIBRARIES} ${ISL_LIBRARIES} ${ATEN_LIBRARIES} pthread) -if (WITH_BINDINGS) - add_dependencies(test_basic generate_isl_cpp_h) -endif() +add_dependencies(test_basic generate_isl_cpp_h) ################################################################################ # Core library only tests From a1ff11ac6e487522a929c4e4fe47ee1e27196e3c Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 19 Jul 2018 17:20:28 +0200 Subject: [PATCH 02/85] generate templated isl types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Templated isl types keep track of the number and nature of tuples in the spaces of an isl object as well as (optionally) their internal structure. This allows the compiler to check whether it makes sense to combine pairs of objects. Static methods are matched based on their return kind. That is, when using static methods, the user needs to provide template arguments that correspond to the return value. It is not clear if this is always the most obvious/convenient choice. If fact, since static methods require the user to explicitly specify the template arguments, they are not very convenient to use. Some static methods therefore also give rise to more convenient, non-static methods in the templated interface. In particular, for each (static) "from" method, a "to*" method is added to the class of the argument of the method. Similarly, for each conversion constructor, an "as*" method is introduced. The difference between "to*" and "as*" is the same as the difference between "from" and conversion, where the "from" method may lose information, while conversion does not. The use of templates to keep track of the number and internal structure of spaces of isl objects has been applied before in an unpublished C++ library by Armin Größlinger. --- CMakeLists.txt | 23 +- isl_interface/generate_template_isl.cc | 1711 ++++++++++++++++++++++++ tc/external/detail/islpp.h | 2 + 3 files changed, 1734 insertions(+), 2 deletions(-) create mode 100644 isl_interface/generate_template_isl.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 30a6e721c..3666cbd9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,6 +225,7 @@ message(STATUS "Found ATen.so file: ${ATEN_LIBRARIES}") ################################################################################ # use locally generated C++ bindings include_directories(AFTER ${PROJECT_SOURCE_DIR}/isl_interface/include) +include_directories(AFTER ${CMAKE_CURRENT_BINARY_DIR}/isl_interface/include) include_directories(AFTER ${PROJECT_SOURCE_DIR}/third-party/islpp/include) include_directories(AFTER ${CMAKE_CURRENT_BINARY_DIR}/third-party/islpp/include) add_subdirectory(external/isl) @@ -336,14 +337,32 @@ endif() SET(ISL_CPP_H "${CMAKE_CURRENT_LIST_DIR}/isl_interface/include/isl/cpp.h") +add_executable(generate_template_isl isl_interface/generate_template_isl.cc) + +find_program(CLANG_FORMAT_BIN clang-format PATHS ${CLANG_PREFIX} + PATH_SUFFIXES bin + NO_DEFAULT_PATH) + +SET(ISL_TEMPLATE_CPP_DIR + "${CMAKE_CURRENT_BINARY_DIR}/isl_interface/include/isl") +SET(ISL_TEMPLATE_CPP_H "${ISL_TEMPLATE_CPP_DIR}/template_cpp.h") +add_custom_command( + OUTPUT ${ISL_TEMPLATE_CPP_H} + DEPENDS ${ISL_CPP_H} + DEPENDS generate_template_isl + COMMAND mkdir -p ${ISL_TEMPLATE_CPP_DIR} + COMMAND generate_template_isl < ${ISL_CPP_H} > ${ISL_TEMPLATE_CPP_H} + COMMAND ${CLANG_FORMAT_BIN} -i ${ISL_TEMPLATE_CPP_H} +) + if (WITH_BINDINGS) add_subdirectory(isl_interface) # generate_isl_cpp_h is the dependency that should be used # by code that depends on the isl C++ bindings. add_custom_target(generate_isl_cpp_h - DEPENDS generate_isl_cpp_h_core) + DEPENDS generate_isl_cpp_h_core ${ISL_TEMPLATE_CPP_H}) else() add_custom_target(generate_isl_cpp_h - DEPENDS) + DEPENDS ${ISL_TEMPLATE_CPP_H}) endif() diff --git a/isl_interface/generate_template_isl.cc b/isl_interface/generate_template_isl.cc new file mode 100644 index 000000000..2f34e617a --- /dev/null +++ b/isl_interface/generate_template_isl.cc @@ -0,0 +1,1711 @@ +/** + * Copyright (c) 2018, Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Fixed initial part of the output. + */ +constexpr auto header = R"CPP( +// Template kind argument corresponding to a (collection of) anonymous space(s) +// or to a missing name. +struct Anonymous; + +// Template kind argument wrapping a pair of kinds and a given name. +template +struct NamedPair; + +// Template kind argument wrapping a pair of kinds without name. +template +using Pair = NamedPair; +)CPP"; + +/* + * Fixed final part of the output. + */ +constexpr auto footer = R"CPP( +// The *AffOn type represent affine functions on a domain. +// The kind of such an affine function is that of the domain combined +// with an anonymous range. +template +using AffOn = Aff; + +template +using PwAffOn = PwAff; + +template +using UnionPwAffOn = UnionPwAff; + +template +using AffListOn = AffList; + +template +using PwAffListOn = PwAffList; + +template +using UnionPwAffListOn = UnionPwAffList; +)CPP"; + +/* + * Drop the "isl::" namespace specifier, if any. + */ +static std::string dropIslNamespace(std::string type) { + return std::regex_replace(type, std::regex("isl::"), ""); +} + +/* + * The type of an isl object in the standard C++ interface. + */ +using IslType = std::string; + +/* + * A Kind represents a collection of spaces with a fixed number of tuples. + * Each tuple represents a collections of space tuples and is identified + * by a name and, optionally, two children. + * A missing name is represented by the name "Anonymous". + */ +struct Tuple { + Tuple(const char* name) : name(name) {} + Tuple(const Tuple& t1, const Tuple& t2) + : name("Anonymous"), children({t1, t2}) {} + Tuple(const char* name, const Tuple& t1, const Tuple& t2) + : name(name), children({t1, t2}) {} + std::string name; + std::vector children; + bool operator<(const Tuple& other) const { + if (name != other.name) { + return name < other.name; + } + if (children.size() != other.children.size()) { + return children.size() < other.children.size(); + } + for (size_t i = 0; i < children.size(); ++i) { + if (children[i] != other.children[i]) { + return children[i] < other.children[i]; + } + } + return false; + } + bool operator==(const Tuple& other) const { + return name == other.name && children == other.children; + } + bool operator!=(const Tuple& other) const { + return !(*this == other); + } +}; +using Kind = std::vector; + +/* + * A generic signature, either in terms of the isl type or + * in terms of the space kinds. + */ +template +struct Signature { + Type returnType; + std::vector argTypes; +}; + +/* + * A method exported by the standard C++ interface. + */ +struct Method { + std::string name; + Signature signature; +}; + +/* + * The collection of exported C++ methods, per class name, + * along with special "#to" and "#as" methods. + * A "#to" method is added for each "from" method (with arguments reversed), + * while an "#as" method is added for each conversion constructor. + */ +using Exported = std::unordered_map>; + +/* + * A class is the templated isl interface. + * The "kinds" array specifies all the different kinds + * that this class may have. + */ +struct Class { + std::string name; + std::vector kinds; +}; + +/* + * A Kind with zero tuples. + */ +static Kind paramsKind() { + return {}; +} + +/* + * A Kind with a single tuple. + */ +static Kind setKind() { + return {"Domain"}; +} + +/* + * A Kind with two tuples. + */ +static Kind mapKind() { + return {"Domain", "Range"}; +} + +/* + * For each class in the regular C++ interface, + * the corresponding class in the templated interface, + * including a list of possible basic kinds. + */ +static const std::unordered_map classes{ + {"space", {"Space", {paramsKind(), setKind(), mapKind()}}}, + {"multi_id", {"MultiId", {setKind()}}}, + {"multi_val", {"MultiVal", {setKind()}}}, + {"set", {"Set", {paramsKind(), setKind()}}}, + {"map", {"Map", {mapKind()}}}, + {"aff", {"Aff", {setKind(), mapKind()}}}, + {"aff_list", {"AffList", {setKind(), mapKind()}}}, + {"pw_aff", {"PwAff", {setKind(), mapKind()}}}, + {"union_pw_aff", {"UnionPwAff", {setKind(), mapKind()}}}, + {"multi_aff", {"MultiAff", {setKind(), mapKind()}}}, + {"pw_aff_list", {"PwAffList", {setKind(), mapKind()}}}, + {"union_pw_aff_list", {"UnionPwAffList", {setKind(), mapKind()}}}, + {"multi_union_pw_aff", {"MultiUnionPwAff", {setKind(), mapKind()}}}, + {"union_pw_multi_aff", {"UnionPwMultiAff", {setKind(), mapKind()}}}, + {"union_set", {"UnionSet", {paramsKind(), setKind()}}}, + {"union_map", {"UnionMap", {mapKind()}}}, + {"map_list", {"MapList", {mapKind()}}}, + {"union_access_info", {"UnionAccessInfo", {mapKind()}}}, + {"union_flow", {"UnionFlow", {mapKind()}}}, + {"stride_info", {"StrideInfo", {mapKind()}}}, + {"fixed_box", {"FixedBox", {mapKind()}}}, +}; + +/* + * Create an object living in the parameter space. + */ +static Signature createParams() { + return {{}, {}}; +} + +/* + * Create an object living in a collection of set spaces. + */ +static Signature createSet() { + return {{"Domain"}, {}}; +} + +static Signature change_wrapped_set() { + return {{{"ModifiedWrap", "WrappedDomain", "WrappedRange"}}, + {{{"Wrap", "WrappedDomain", "WrappedRange"}}}}; +} + +/* + * Create an object living in a collection of map spaces. + */ +static Signature createMap() { + return {{"Domain", "Range"}, {}}; +} + +/* + * Take an object living in a collection of set spaces and + * a map with this collection as domain and return + * an object in the corresponding range. + */ +static Signature applySet() { + return {{"Range"}, {{"Domain"}, {"Domain", "Range"}}}; +} + +/* + * Take an object living in a collection of map spaces and + * another map with with the same domain and return + * an object in the original collection with the domain + * replaced by the range of the second map. + */ +static Signature applyDomain() { + return {{"Range3", "Range"}, {{"Domain", "Range"}, {"Domain", "Range3"}}}; +} + +/* + * Take an object living in a collection of map spaces and + * another map with with the range of the first as domain and return + * an object in the original collection with the range + * replaced by the range of the second map. + */ +static Signature applyRange() { + return {{"Domain", "Range2"}, {{"Domain", "Range"}, {"Range", "Range2"}}}; +} + +/* + * Perform the same operation as applyRange, but with the arguments + * interchanged. + */ +static Signature preimageDomain() { + return {{"Domain2", "Range"}, {{"Domain", "Range"}, {"Domain2", "Domain"}}}; +} + +/* + * Return an object that, like the input, lives in a parameter space. + */ +static Signature updateParams() { + return {{}, {{}}}; +} + +/* + * Return an object that, like the two inputs, lives in a parameter space. + */ +static Signature updateParamsBinary() { + return {{}, {{}, {}}}; +} + +/* + * Return an object that lives in the same collection of set spaces + * as the first input and that takes an object living in a parameter space + * as second input. + */ +static Signature updateSetParams() { + return {{"Domain"}, {{"Domain"}, {}}}; +} + +/* + * Return an object that lives in the same collection of set spaces + * as the input. + */ +static Signature updateSet() { + return {{"Domain"}, {{"Domain"}}}; +} + +/* + * Return an object that lives in a (potentially) different + * collection of set spaces compared to the input. + */ +static Signature changeSet() { + return {{"ModifiedDomain"}, {{"Domain"}}}; +} + +/* + * Return an object that lives in the same collection of set spaces + * as the two inputs. + */ +static Signature updateSetBinary() { + return {{"Domain"}, {{"Domain"}, {"Domain"}}}; +} + +/* + * Return an object that lives in the same collection of map spaces + * as the input. + */ +static Signature updateMap() { + return {{"Domain", "Range"}, {{"Domain", "Range"}}}; +} + +/* + * Return an object that lives in the same collection of map spaces + * as the two inputs. + */ +static Signature updateMapBinary() { + return {{"Domain", "Range"}, {{"Domain", "Range"}, {"Domain", "Range"}}}; +} + +/* + * Return an object that lives in the same collection of map spaces + * as the first input and that takes an object living in a parameter space + * as second input. + */ +static Signature updateMapParams() { + return {{"Domain", "Range"}, {{"Domain", "Range"}, {}}}; +} + +/* + * Return an object that lives in the same collection of map spaces + * as the first input and that takes an object living in the domain + * of the first input as second input. + */ +static Signature updateMapDomain() { + return {{"Domain", "Range"}, {{"Domain", "Range"}, {"Domain"}}}; +} + +/* + * Return an object that lives in the same collection of map spaces + * as the first input and that takes an object living in the range + * of the first input as second input. + */ +static Signature updateMapRange() { + return {{"Domain", "Range"}, {{"Domain", "Range"}, {"Range"}}}; +} + +/* + * Return an object that lives in a collection of map spaces + * where the range is potentially different from that of the input. + */ +static Signature changeRange() { + return {{"Domain", "ModifiedRange"}, {{"Domain", "Range"}}}; +} + +/* + * Return a map with the input collection of spaces as both domain and range. + */ +static Signature mapOnSet() { + return {{"Domain", "Domain"}, {{"Domain"}}}; +} + +/* + * Return a map with the domain of the input collection of spaces + * as both domain and range. + */ +static Signature mapOnDomain() { + return {{"Domain", "Domain"}, {{"Domain", "Range"}}}; +} + +/* + * Return a set given an object living in a parameter space. + */ +static Signature setFromParams() { + return {{"Domain"}, {{}}}; +} + +/* + * Return a map given an object living in a parameter space. + */ +static Signature mapFromParams() { + return {{"Domain", "Range"}, {{}}}; +} + +/* + * Return a map with the input collection of spaces as domain. + */ +static Signature mapFromDomain() { + return {{"Domain", "Range"}, {{"Domain"}}}; +} + +/* + * Given an object living in a collection of set spaces, + * return an object living in a parameter space. + */ +static Signature setParams() { + return {{}, {{"Domain"}}}; +} + +/* + * Given an object living in a collection of map spaces, + * return an object living in a parameter space. + */ +static Signature mapParams() { + return {{}, {{"Domain", "Range"}}}; +} + +/* + * Given two objects living in the collection of set spaces, + * return an object living in a parameter space. + */ +static Signature setParamsBinary() { + return {{}, {{"Domain"}, {"Domain"}}}; +} + +/* + * Given an object living in a collection of map spaces, + * return an object living in the domain. + */ +static Signature mapDomain() { + return {{"Domain"}, {{"Domain", "Range"}}}; +} + +/* + * Given an object living in a collection of map spaces, + * return an object that maps such objects to their domains. + */ +static Signature mapDomainMap() { + return {{{"Domain", "Range"}, "Domain"}, {{"Domain", "Range"}}}; +} + +/* + * Given an object living in a collection of map spaces, + * return an object that maps such objects to their domains. + * For use on static methods. + */ +static Signature mapDomainMapStatic() { + return {{{"Range", "Domain2"}, "Range"}, {{"Range", "Domain2"}}}; +} + +/* + * Given an object living in a collection of map spaces, + * return an object that maps such objects to their ranges. + * For use on static methods. + */ +static Signature mapRangeMapStatic() { + return {{{"Domain2", "Range"}, "Range"}, {{"Domain2", "Range"}}}; +} + +/* + * Given an object living in a collection of set spaces wrapping map spaces, + * return an object that maps such objects to their wrapped ranges. + * For use on static methods. + */ +static Signature setWrappedRangeMapStatic() { + return {{{"Wrap", "WrappedDomain", "WrappedRange"}, "WrappedRange"}, + {{{"Wrap", "WrappedDomain", "WrappedRange"}}}}; +} + +/* + * Given a pair of objects living in the same collection of map spaces, + * return an object living in their domain. + */ +static Signature mapDomainBinary() { + return {{"Domain"}, {{"Domain", "Range"}, {"Domain", "Range"}}}; +} + +/* + * Given a pair of objects living in the collections of map spaces + * with the same range, + * return an object living in a map between their domains. + */ +static Signature mapDomainBinaryMap() { + return {{"Domain", "Domain2"}, {{"Domain", "Range"}, {"Domain2", "Range"}}}; +} + +/* + * Given an object living in a collection of map spaces, + * return an object living in the range. + */ +static Signature mapRange() { + return {{"Range"}, {{"Domain", "Range"}}}; +} + +/* + * Given an object living in a collection of domain set spaces and + * an object living in a collection of range set spaces, + * return the combined collection of map spaces. + */ +static Signature mapFromDomainAndRange() { + return {{"Domain", "Range"}, {{"Domain"}, {"Range"}}}; +} + +/* + * Performs the same operation as mapFromDomainAndRange, + * but with the arguments reversed. + */ +static Signature mapFromRangeAndDomain() { + return {{"Domain2", "Domain"}, {{"Domain"}, {"Domain2"}}}; +} + +/* + * Given an object living in a collection of map spaces, + * return one where domain and range have been interchanged. + */ +static Signature mapReverse() { + return {{"Range", "Domain"}, {{"Domain", "Range"}}}; +} + +/* + * Given an object living in a collection of map spaces, + * relating the same collection of set spaces as well + * another map on the same domain, + * return an object living in the same collection as the first input. + */ +static Signature mapTest() { + return {{"Domain", "Domain"}, {{"Domain", "Domain"}, {"Domain", "Range2"}}}; +} + +/* + * Given a pair of objects living in collections of map spaces + * with the same domain, return an object in the range product. + */ +static Signature mapRangeProduct() { + return {{"Domain", {"Range", "Range3"}}, + {{"Domain", "Range"}, {"Domain", "Range3"}}}; +} + +/* + * Given a pair of objects living in collections of map spaces + * with the same domain, return an object in the flat range product. + */ +static Signature mapFlatRangeProduct() { + return {{"Domain", "Range2"}, {{"Domain", "Range"}, {"Domain", "Range3"}}}; +} + +/* + * Given an object living in a collections of map spaces + * with nested domains, return the result of currying. + */ +static Signature mapCurry() { + return {{"Domain2", {"Range2", "Range"}}, {{{"Domain2", "Range2"}, "Range"}}}; +} + +/* + * Given an object living in a collections of map spaces + * with nested range, return the result of uncurrying. + */ +static Signature mapUncurry() { + return {{{"Domain", "Domain2"}, "Range2"}, + {{"Domain", {"Domain2", "Range2"}}}}; +} + +/* + * Given an object living in a collections of map spaces + * with nested domains, return an object in a collection of spaces + * where the domain has been replaced by its nested domain. + */ +static Signature mapDomainFactorDomain() { + return {{"Domain2", "Range"}, {{{"Domain2", "Range2"}, "Range"}}}; +} + +/* + * Given an object living in a collection of map spaces, + * return an object in the collection of wrapped set spaces. + */ +static Signature mapWrap() { + return {{{"Domain", "Range"}}, {{"Domain", "Range"}}}; +} + +/* + * Given a pair of objects living in collections of set spaces, + * return an object living in the product. + */ +static Signature setProduct() { + return {{{"Domain", "Range"}}, {{"Domain"}, {"Range"}}}; +} + +/* + * Given an object living in a collection of wrapped set spaces, + * return an object in the corresponding collection of map spaces. + */ +static Signature setUnwrap() { + return {{"MapDomain", "MapRange"}, {{{"MapDomain", "MapRange"}}}}; +} + +/* + * Given a pair of objects living in collections of map spaces + * with the same domain, return an object in the result of zipping. + */ +static Signature mapZip() { + return {{{"WrappedDomain1", "WrappedDomain2"}, + {"WrappedRange1", "WrappedRange2"}}, + {{{"WrappedDomain1", "WrappedRange1"}, + {"WrappedDomain2", "WrappedRange2"}}}}; +} + +/* + * Given an object living in a collection of map spaces, + * return an anonymous object defined over the same domain. + */ +static Signature mapAnonymous() { + return {{"Domain", "Anonymous"}, {{"Domain", "Range"}}}; +} + +/* + * Update an object living in a collection of map spaces + * with an anonymous object defined over the same domain. + */ +static Signature updateMapAnonymous() { + return {{"Domain", "Range"}, {{"Domain", "Range"}, {"Domain", "Anonymous"}}}; +} + +/* + * Update an object living in a collection of range set spaces + * with an anonymous object defined over some domain + * to form a map from the domain to the range. + */ +static Signature updateRangeAnonymous() { + return {{"Domain", "Range"}, {{"Range"}, {"Domain", "Anonymous"}}}; +} + +/* + * Potential kind signatures for methods with the given name. + */ +static const std::unordered_map>> + signatures{ + {"add_param", {updateParams(), updateSet()}}, + {"align_params", {updateSetParams(), updateMapParams()}}, + {"apply", {applySet(), applyRange()}}, + {"apply_domain", {applyDomain()}}, + {"preimage_domain", {preimageDomain()}}, + {"pullback", {preimageDomain()}}, + {"apply_range", {applyRange()}}, + {"coalesce", {updateParams(), updateSet(), updateMap()}}, + {"eq_at", {mapTest()}}, + {"ge_set", {setParamsBinary()}}, + {"get_space", {updateParams(), updateSet(), updateMap()}}, + {"gist", {updateSetBinary(), updateMapBinary()}}, + {"intersect", + {updateParamsBinary(), updateSetBinary(), updateMapBinary()}}, + {"intersect_domain", {updateMapDomain()}}, + {"intersect_range", {updateMapRange()}}, + {"intersect_params", {updateSetParams(), updateMapParams()}}, + {"lt_set", {mapDomainBinary()}}, + {"le_set", {mapDomainBinary()}}, + {"eq_set", {mapDomainBinary()}}, + {"lt_map", {mapDomainBinaryMap()}}, + {"gt_map", {mapDomainBinaryMap()}}, + {"params", {setParams(), mapParams()}}, + {"from_params", {setFromParams()}}, + {"map_from_set", {mapOnSet()}}, + {"add_named_tuple_id_ui", {setFromParams()}}, + {"add_unnamed_tuple_ui", {setFromParams(), mapFromDomain()}}, + {"product", {setProduct()}}, + {"map_from_domain_and_range", {mapFromDomainAndRange()}}, + {"domain", {mapDomain()}}, + {"domain_map", {mapDomainMap()}}, + {"range", {mapRange()}}, + {"reverse", {mapReverse()}}, + {"subtract", {updateSetBinary(), updateMapBinary()}}, + {"unbind_params_insert_domain", {mapFromRangeAndDomain()}}, + {"sum", {updateMapBinary()}}, + {"unite", {updateSetBinary(), updateMapBinary()}}, + {"union_add", {updateMapBinary()}}, + {"range_product", {mapRangeProduct()}}, + {"flat_range_product", {mapFlatRangeProduct()}}, + {"curry", {mapCurry()}}, + {"uncurry", {mapUncurry()}}, + {"domain_factor_domain", {mapDomainFactorDomain()}}, + {"wrap", {mapWrap()}}, + {"unwrap", {setUnwrap()}}, + {"zip", {mapZip()}}, + {"add", {updateSetBinary(), updateMapBinary()}}, + {"sub", {updateSetBinary(), updateMapBinary()}}, + {"mul", {updateSetBinary()}}, + {"div", {updateSetBinary()}}, + {"mod", + {updateSetBinary(), updateMapBinary(), updateSet(), updateMap()}}, + {"get_at", {updateSet(), updateMap()}}, + {"get_map_list", {updateMap()}}, + {"get_aff", {mapAnonymous()}}, + {"set_aff", {updateMapAnonymous()}}, + {"get_aff_list", {mapAnonymous()}}, + {"get_union_pw_aff", {mapAnonymous()}}, + {"set_union_pw_aff", {updateMapAnonymous()}}, + {"get_union_pw_aff_list", {mapAnonymous()}}, + {"pos_set", {setParams(), mapDomain()}}, + {"nonneg_set", {setParams(), mapDomain()}}, + {"zero_set", {setParams(), mapDomain()}}, + {"zero_union_set", {setParams(), mapDomain()}}, + {"add_constant", {updateSet(), updateMap()}}, + {"add_constant_si", {updateSet(), updateMap()}}, + {"set_val", {updateSet()}}, + {"floor", {updateMap()}}, + {"neg", {updateSet(), updateMap()}}, + {"drop", {updateMap()}}, + {"scale", {updateMap(), updateMapRange()}}, + {"scale_down", {updateMap(), updateMapRange()}}, + {"set_set_tuple_id", {change_wrapped_set(), changeSet()}}, + {"set_tuple_id", {change_wrapped_set(), changeSet()}}, + {"set_range_tuple_id", {changeSet(), changeRange()}}, + {"get_range_stride_info", {mapAnonymous()}}, + {"get_offset", {updateMap()}}, + {"get_range_simple_fixed_box_hull", {updateMap()}}, + {"set_may_source", {updateMapBinary()}}, + {"set_schedule", {updateMap()}}, + {"compute_flow", {updateMap()}}, + {"get_may_dependence", {mapOnDomain()}}, + }; + +/* + * Potential kind signatures for classes and methods with the given names. + * These override the generic signatures above. + */ +static const std:: + map, std::vector>> + specificSignatures{ + {{"set", "identity"}, {mapOnSet()}}, + {{"union_set", "get_space"}, {setParams()}}, + {{"union_map", "get_space"}, {setParams()}}, + {{"union_pw_aff", "get_space"}, {setParams()}}, + {{"union_pw_multi_aff", "get_space"}, {setParams()}}, + {{"union_set", "universe"}, {updateSet()}}, + {{"union_map", "universe"}, {updateMap()}}, + // should be called "gist_domain" + {{"multi_union_pw_aff", "gist"}, {updateMapDomain()}}, + {{"multi_union_pw_aff", "get_space"}, {mapRange()}}, + {{"aff_list", "reverse"}, {updateMap()}}, + {{"pw_aff_list", "reverse"}, {updateMap()}}, + {{"union_pw_aff_list", "reverse"}, {updateMap()}}, + {{"map_list", "reverse"}, {updateMap()}}, + }; + +/* + * Potential kind signatures for static methods with the given name. + */ +static const std::unordered_map>> + staticSignatures{ + {"from", {updateMap()}}, + {"identity", {updateMap()}}, + {"param_on_domain_space", {setFromParams()}}, + {"param_on_domain", {mapFromDomain()}}, + {"empty", {updateParams(), updateSet(), updateMap()}}, + {"universe", {updateParams(), updateSet(), updateMap()}}, + {"zero", {updateSet(), updateMap()}}, + {"zero_on_domain", {mapFromDomain()}}, + {"from_domain", {mapFromDomain()}}, + }; + +/* + * Potential kind signatures for classes and + * static methods with the given names. + * These override the generic static signatures above. + */ +static const std:: + map, std::vector>> + specificStaticSignatures{ + {{"multi_aff", "domain_map"}, {mapDomainMapStatic()}}, + {{"multi_aff", "range_map"}, {mapRangeMapStatic()}}, + {{"multi_aff", "wrapped_range_map"}, {setWrappedRangeMapStatic()}}, + {{"union_set", "empty"}, {setFromParams()}}, + {{"union_map", "empty"}, {mapFromParams()}}, + }; + +/* + * A constructor, described by the argument types and + * one or more corresponding kind signatures. + */ +struct Constructor { + std::vector argTypes; + std::vector> signatures; +}; + +/* + * For each class in the regular C++ interface, + * a hard-coded list of constructors that need to be exported. + */ +static const std::unordered_map> + constructors{ + {"multi_id", {{{"space", "id_list"}, {updateSet()}}}}, + {"multi_val", {{{"space", "val_list"}, {updateSet()}}}}, + {"multi_aff", {{{"space", "aff_list"}, {updateMapAnonymous()}}}}, + {"union_pw_aff", {{{"union_set", "val"}, {mapFromDomain()}}}}, + {"multi_union_pw_aff", + {{{"space", "union_pw_aff_list"}, {updateRangeAnonymous()}}, + {{"union_set", "multi_val"}, {mapFromDomainAndRange()}}}}, + {"map", {{{"multi_aff"}, {updateMap()}}}}, + {"union_map", {{{"map"}, {updateMap()}}}}, + {"union_set", {{{"set"}, {updateSet()}}}}, + {"pw_aff", {{{"aff"}, {updateSet(), updateMap()}}}}, + {"aff_list", + {{{"aff"}, {updateSet(), updateMap()}}, + {{"ctx", "int"}, {createSet(), createMap()}}}}, + // should be replaced by a constructor without int argument + {"space", {{{"ctx", "int"}, {createParams()}}}}, + {"union_pw_aff_list", {{{"ctx", "int"}, {createSet(), createMap()}}}}, + {"union_access_info", {{{"union_map"}, {updateMap()}}}}, + }; + +/* + * Is "name" the name of a "foreach" method? + */ +static bool isForeach(const std::string& name) { + return name.find("foreach_") != std::string::npos; +} + +/* + * A collection of substitutions of names by tuples. + * There are two kinds of names, those that represent the leave tuples + * in a nesting structure and those that represent the names + * of a particular nested sequence of tuples. + * The substitution of the second kind is always + * (a tuple constructed from) a name. + */ +using Subs = std::map; + +/* + * Collect all non-anonymous template arguments from the tuple and + * add them to the given set. + */ +static std::set collect( + const Tuple& tuple, + std::set set = {}) { + if (tuple.name != "Anonymous") { + set.insert(tuple.name); + } + for (const auto& el : tuple.children) { + set = collect(el, set); + } + return set; +} + +/* + * Collect all non-anonymous template arguments from the kind and + * add them to the given set. + */ +static std::set collect( + const Kind& kind, + std::set set = {}) { + for (auto base : kind) { + set = collect(base, set); + } + return set; +} + +/* + * Collect all non-anonymous template arguments from the kind signature and + * add them to the given set. + */ +static std::set collect(const Signature& signature) { + auto set = collect(signature.returnType); + for (auto arg : signature.argTypes) { + set = collect(arg, set); + } + return set; +} + +/* + * Print "s" to "os", for use in template functions. + */ +static void print(std::ostream& os, const std::string& s) { + os << s; +} + +/* + * Print a tuple to "os". + * If the tuple is represented by a name, that name gets printed. + * Otherwise, it represents a nested pairs of tuples and is + * printed as a "Pair" or as a "NamedPair" depending + * on whether it's name is "Anonymous". + */ +static void print(std::ostream& os, const Tuple& tuple) { + if (tuple.children.size() == 2) { + if (tuple.name == "Anonymous") { + os << "Pair<"; + } else { + os << "NamedPair<"; + print(os, tuple.name); + os << ","; + } + print(os, tuple.children[0]); + os << ","; + print(os, tuple.children[1]); + os << ">"; + } else { + print(os, tuple.name); + } +} + +/* + * Print a collection of template arguments, where each argument + * is preceded by "qualifier" (possibly an empty string). + */ +template +static void printTemplateArguments( + const C collection, + const std::string& qualifier) { + std::cout << "<"; + bool first = true; + for (auto s : collection) { + if (!first) { + std::cout << ", "; + } + std::cout << qualifier; + print(std::cout, s); + first = false; + } + std::cout << ">"; +} + +/* + * Print a template declaring all the elements in "t" + * as template arguments. + */ +template +static void printTemplate(const T& t) { + std::cout << "template "; + printTemplateArguments(t, "typename "); + std::cout << "\n"; +} + +/* + * Print a class declaration for "name" with partial + * template specialization specified by "kind". + */ +static void printClassDeclaration(const std::string& name, const Kind& kind) { + printTemplate(collect(kind, {})); + std::cout << "struct " << name; + printTemplateArguments(kind, ""); +} + +/* + * Print forward declarations for all exported classes + * with template parameter packs. + */ +static void printForwardDeclarations() { + for (auto kvp : classes) { + std::cout << "\n"; + std::cout << "template \n"; + std::cout << "struct " << kvp.second.name; + std::cout << ";\n"; + } +} + +/* + * Specialize "name" based on the given substitutions. + * If "name" appears among the substitutions, then return the result + * of the substitution. Otherwise, return "name" itself (as a Tuple). + */ +static Tuple specialize(const std::string& name, const Subs& subs) { + if (subs.count(name) != 0) { + return subs.at(name); + } else { + return name.c_str(); + } +} + +/* + * Recursively specialize "tuple" based on the given substitutions. + */ +static Tuple specialize(const Tuple& tuple, const Subs& subs) { + if (tuple.children.size() == 0) { + return specialize(tuple.name, subs); + } else { + return Tuple{specialize(tuple.name, subs).name.c_str(), + specialize(tuple.children[0], subs), + specialize(tuple.children[1], subs)}; + } +} + +/* + * Specialize "kind" based on the given substitutions. + */ +static Kind specialize(const Kind& kind, const Subs& subs) { + if (subs.size() == 0) { + return kind; + } + Kind specialized; + for (auto base : kind) { + specialized.emplace_back(specialize(base, subs)); + } + return specialized; +} + +/* + * Specialize the given vector of kinds based on the given substitutions. + */ +static std::vector specialize( + const std::vector& vector, + const Subs& subs) { + std::vector specialized; + for (auto kind : vector) { + specialized.emplace_back(specialize(kind, subs)); + } + return specialized; +} + +/* + * Specialize the given signature based on the given substitutions. + */ +static Signature specialize( + const Signature& signature, + const Subs& subs) { + return {specialize(signature.returnType, subs), + specialize(signature.argTypes, subs)}; +} + +/* + * Print a template for all the template arguments in "signature" + * that do not already appear in "classKind", if there are any. + */ +static void printExtraTemplate( + const Kind& classKind, + const Signature& signature) { + auto classBase = collect(classKind, {}); + classBase.insert("Anonymous"); + auto signatureBase = collect(signature); + std::vector extra; + for (auto base : signatureBase) { + if (classBase.count(base) == 0) { + extra.emplace_back(base); + } + } + if (extra.size() != 0) { + printTemplate(extra); + } +} + +/* + * Print the templated type corresponding to the given isl type and + * the given kind. + */ +static void printTemplatedType(const IslType& type, const Kind& kind) { + const auto& templateClass = classes.at(type); + std::cout << templateClass.name; + printTemplateArguments(kind, ""); +} + +/* + * Print the templated return type of "method" with kind information + * taken from "signature". + */ +static void printTemplatedReturnType( + const Signature& signature, + const Method& method) { + printTemplatedType(method.signature.returnType, signature.returnType); +} + +/* + * Print the templated argument types specified by "argTypes" and + * "signature". For non-static methods, the first element of + * the argument types of "signature" corresponds to the object + * on which the method is called and is therefore skipped. + * Only elements in "argTypes" that have a corresponding + * templated class type consume an element in the argument + * types of "signature". + */ +static void printTemplatedArgumentTypes( + const std::vector& argTypes, + const Signature& signature, + bool isStatic) { + std::cout << "("; + size_t j = isStatic ? 0 : 1; + for (size_t i = 0; i < argTypes.size(); ++i) { + if (i > 0) { + std::cout << ", "; + } + std::cout << "const "; + const IslType& type = argTypes[i]; + if (classes.count(type) == 0) { + std::cout << type; + } else { + printTemplatedType(type, signature.argTypes[j++]); + } + std::cout << "& arg" << i; + } + std::cout << ")"; +} + +/* + * Return a substitution that extends "subs" and turns "src" into "dst", + * assuming that "dst" is a special case of "src". + */ +static Subs specializer( + const std::vector& dst, + const std::vector& src, + Subs subs = {}) { + for (size_t i = 0; i < src.size(); ++i) { + if (src[i].children.size() == 0) { + subs.emplace(src[i].name, dst[i]); + } else if (src[i].children.size() == dst[i].children.size()) { + subs.emplace(src[i].name, dst[i].name.c_str()); + subs = specializer(dst[i].children, src[i].children, subs); + } + } + return subs; +} + +/* + * Specialize "signature" to "classKind" based on a specialization + * of the object type to "classKind". + */ +static Signature specialize( + const Signature& signature, + const Kind& classKind) { + Subs subs = specializer(classKind, signature.argTypes[0]); + return specialize(signature, subs); +} + +/* + * Print a templated version of the method "method" + * with the given space kind signature + * as part of a class definition of a templated class + * derived from "base" with the given specialized kind. + * + * The templated method simply calls the corresponding + * method in the base class and converts the result + * to a templated type. + * The return type is always templated because + * methods that do not return a type that can/should + * be templated can simply be called directly in the base class. + */ +static bool printMethod( + const std::string& base, + const Kind& classKind, + const Signature& signature, + const Method& method, + bool isStatic = false) { + printExtraTemplate(classKind, signature); + if (isStatic) { + std::cout << "static "; + } + std::cout << "inline "; + printTemplatedReturnType(signature, method); + std::cout << " "; + std::cout << method.name; + printTemplatedArgumentTypes(method.signature.argTypes, signature, isStatic); + if (!isStatic) { + std::cout << " const"; + } + std::cout << " {\n"; + std::cout << "auto res = "; + if (!isStatic) { + std::cout << "this->"; + } + std::cout << base << "::" << method.name << "("; + for (size_t i = 0; i < method.signature.argTypes.size(); ++i) { + if (i > 0) { + std::cout << ", "; + } + std::cout << "arg" << i; + } + std::cout << ");\n"; + std::cout << "return "; + printTemplatedReturnType(signature, method); + std::cout << "(res);\n"; + std::cout << "}\n"; + return true; +} + +/* + * Print a method called to*, derived from a "from" method + * with return value and argument interchanged. + * The return type is included in the name of the method. + */ +static void printTo(const Signature& signature, const Method& method) { + std::cout << "inline "; + printTemplatedReturnType(signature, method); + std::cout << " to" << classes.at(method.signature.returnType).name + << "() const {\n"; + std::cout << "return "; + printTemplatedReturnType(signature, method); + std::cout << "::from(*this);\n"; + std::cout << "}\n"; +} + +/* + * Print a method called as*, derived from a conversion constructor + * with return value and argument interchanged. + * The return type is included in the name of the method. + */ +static void printAs(const Signature& signature, const Method& method) { + std::cout << "inline "; + printTemplatedReturnType(signature, method); + std::cout << " as" << classes.at(method.signature.returnType).name + << "() const {\n"; + std::cout << "return "; + printTemplatedReturnType(signature, method); + std::cout << "(*this);\n"; + std::cout << "}\n"; +} + +/* + * Print a "foreach" method corresponding to "method" + * in the class derived from "base" with the given class kind. + * The "foreach" method calls "method" with a lambda that + * converts the regular isl type to the corresponding + * templated type. + */ +static void printForeach( + const std::string& base, + const Kind& classKind, + const Method& method) { + const auto& fn = method.signature.argTypes[0]; + auto open = fn.find("("); + auto close = fn.find(")", open + 1); + if (close == std::string::npos) { + return; + } + auto argType = fn.substr(open + 1, close - (open + 1)); + if (classes.count(argType) == 0) { + return; + } + std::cout << "inline void " << method.name << "("; + std::cout << fn.substr(0, open + 1); + printTemplatedType(argType, classKind); + std::cout << fn.substr(close); + std::cout << "& fn) const {\n"; + std::cout << "auto lambda = [fn](" << argType << " arg) -> void {\n"; + std::cout << "fn("; + printTemplatedType(argType, classKind); + std::cout << "(arg));"; + std::cout << "};\n"; + std::cout << "this->" << base << "::" << method.name << "(lambda);\n"; + std::cout << "}\n"; +} + +/* + * Return the number of elements in "argTypes" that have a corresponding + * templated type. + */ +static size_t countTemplated(const std::vector& argTypes) { + size_t count = 0; + for (const auto& type : argTypes) { + if (classes.count(type) != 0) { + ++count; + } + } + return count; +} + +/* + * Does "signature" match the static method with the given arguments and + * class kind? + * The number of tuple template arguments + * of the return value needs to match that of the class kind and + * the number of arguments in the signature needs to be equal to + * the number of arguments of the method that have a corresponding + * templated type. + */ +static bool matchesStatic( + const Kind& classKind, + const Signature& signature, + const std::vector& argTypes) { + return signature.returnType.size() == classKind.size() && + countTemplated(argTypes) == signature.argTypes.size(); +} + +/* + * Does "signature" match the given method and class kind? + * Delegate to matchesStatic for static methods. + * For other methods, the number of tuple template arguments + * of the first argument needs to match that of the class kind and + * the number of arguments in the signature needs to be one more + * than the number of arguments of the method that have a corresponding + * templated type, the extra element corresponding to the object + * on which the method is called. + */ +static bool matches( + const Kind& classKind, + const Signature& signature, + const Method& method, + bool isStatic) { + if (isStatic) { + return matchesStatic(classKind, signature, method.signature.argTypes); + } + if (signature.argTypes[0].size() != classKind.size()) { + return false; + } + auto count = countTemplated(method.signature.argTypes); + return signature.argTypes.size() == 1 + count; +} + +/* + * Call "f" on the signature specialized by "subs" + * if it matches the method and class kind. + * For non-static methods, the object kind may be a partial specialization. + * The signature is therefore further specialized to "classKind". + */ +template +static void callIfMatching( + const Kind& classKind, + const Signature& signature, + const Method& method, + bool isStatic, + const Subs& subs, + const Functor& f) { + auto specializedSignature = specialize(signature, subs); + if (matches(classKind, specializedSignature, method, isStatic)) { + if (!isStatic) { + specializedSignature = specialize(specializedSignature, classKind); + } + f(specializedSignature, isStatic); + } +} + +/* + * Call "f" on each of the matching signatures, specialized by "subs", + * for the given method, regular isl class ("base") and + * the given number of template arguments of the matching kind + * (first argument for regular methods and return value for static methods). + * + * Specific signatures override the generic signatures, so they are + * examined first. + */ +template +static void foreachStructureMatchingSignature( + const std::string& base, + const Kind& classKind, + const Method& method, + const Subs& subs, + const Functor& f) { + if (specificSignatures.count({base, method.name}) != 0) { + for (const auto& signature : specificSignatures.at({base, method.name})) { + callIfMatching(classKind, signature, method, false, subs, f); + } + } else if (specificStaticSignatures.count({base, method.name}) != 0) { + for (const auto& signature : + specificStaticSignatures.at({base, method.name})) { + callIfMatching(classKind, signature, method, true, subs, f); + } + } else if (signatures.count(method.name) != 0) { + for (const auto& signature : signatures.at(method.name)) { + callIfMatching(classKind, signature, method, false, subs, f); + } + } else if (staticSignatures.count(method.name) != 0) { + for (const auto& signature : staticSignatures.at(method.name)) { + callIfMatching(classKind, signature, method, true, subs, f); + } + } +} + +/* + * Call "f" on the first matching signature, specialized by "subs", + * for the given method, regular isl class ("base") and the given matching kind + * (first argument for regular methods and return value for static methods). + */ +template +static void onFirstMatchingSignature( + const std::string& base, + const Kind& classKind, + const Method& method, + const Subs& subs, + const Functor& f) { + bool first = true; + foreachStructureMatchingSignature( + base, + classKind, + method, + subs, + [classKind, f, &first](const Signature& signature, bool isStatic) { + const auto& match = + isStatic ? signature.returnType : signature.argTypes[0]; + if (first && match == classKind) { + f(signature, isStatic); + first = false; + } + }); +} + +/* + * Print templated versions of the methods in "methods" + * as part of a class definition of a templated class + * derived from "base" with the given specialized kind. + * "subs" specializes the corresponding generic class kind + * to the specialized class kind. + * The #to, #as and foreach* methods are handled separately. + */ +static void printMethods( + const std::string& base, + const Kind& specializedClassKind, + const std::vector& methods, + const Subs& subs) { + for (auto method : methods) { + onFirstMatchingSignature( + base, + specializedClassKind, + method, + subs, + [base, specializedClassKind, method, subs]( + const Signature& signature, bool isStatic) { + printMethod(base, specializedClassKind, signature, method, isStatic); + }); + if (method.name == "#to" && + classes.count(method.signature.returnType) == 1) { + for (auto returnKind : classes.at(method.signature.returnType).kinds) { + if (specializedClassKind.size() == 2 && returnKind.size() == 2) { + printTo(specialize(updateMap(), subs), method); + } + if (specializedClassKind.size() == 1 && returnKind.size() == 1) { + printTo(specialize(updateSet(), subs), method); + } + } + } else if ( + method.name == "#as" && + classes.count(method.signature.returnType) == 1) { + for (auto returnKind : classes.at(method.signature.returnType).kinds) { + if (specializedClassKind.size() == returnKind.size()) { + for (const auto& constructor : + constructors.at(method.signature.returnType)) { + for (const auto& signature : constructor.signatures) { + if (constructor.argTypes[0] == base && + signature.returnType.size() == specializedClassKind.size()) { + auto specializedSignature = specialize(signature, subs); + printAs(specializedSignature, method); + } + } + } + } + } + } else if (isForeach(method.name)) { + printForeach(base, specializedClassKind, method); + } + } +} + +/* + * Print a constructor for the templated class "className" + * derived from the regular class "base", with the given + * argument types and kind signature. + * + * Each constructor simply calls the constructor of the base class. + */ +static void printConstructor( + const std::string& base, + const std::string& className, + const std::vector& argTypes, + const Signature& signature) { + std::cout << className; + printTemplatedArgumentTypes(argTypes, signature, true); + std::cout << " : " << base << "("; + for (size_t i = 0; i < argTypes.size(); ++i) { + if (i > 0) { + std::cout << ", "; + } + std::cout << "arg" << i; + } + std::cout << ") {}\n"; +} + +/* + * Print a templated version of class "base" called "className" + * for the given specialized class kind. + * "subs" specializes the corresponding generic class kind + * to the specialized class kind. + */ +static void printOneDefinition( + const std::string& base, + const std::string& className, + const Kind& specializedClassKind, + const Exported& exported, + const Subs& subs) { + std::cout << "\n"; + printClassDeclaration(className, specializedClassKind); + std::cout << " : public " << base << " {\n"; + std::cout << className << "() = default;\n"; + std::cout << "explicit " << className << "(const " << base + << "& obj) : " << base << "(obj) {}\n"; + if (constructors.count(base) != 0) { + for (const auto& constructor : constructors.at(base)) { + for (const auto& signature : constructor.signatures) { + const auto& argTypes = constructor.argTypes; + if (matchesStatic(specializedClassKind, signature, argTypes)) { + auto specializedSignature = specialize(signature, subs); + printConstructor( + base, className, constructor.argTypes, specializedSignature); + } + } + } + } + if (exported.count(base) != 0) { + printMethods(base, specializedClassKind, exported.at(base), subs); + } + std::cout << "};\n"; +} + +/* + * Add the specialized kind of each signature for any exported method + * of class "base" with number of template arguments specified + * by "classKind" to "kinds". + * For a non-static signature, add the object kind. + * For a static signature, add the return kind. + */ +static void collectSpecializedKinds( + const std::string& base, + const Kind& classKind, + const Exported& exported, + std::set& kinds) { + for (auto method : exported.at(base)) { + foreachStructureMatchingSignature( + base, + classKind, + method, + {}, + [&kinds](const Signature& signature, bool isStatic) { + if (isStatic) { + kinds.emplace(signature.returnType); + } else { + kinds.emplace(signature.argTypes[0]); + } + }); + } +} + +/* + * Print templated versions of the exported methods for the class + * with name "base" in the regular interface and name "className" + * in the templated interface and for a number of template arguments + * as specified by "classKind". + * + * Besides the generic version described by "classKind", also + * print definitions for specialized versions where one or more + * of the template arguments have been specialized to + * a nested tuple structure. + * In particular, print a specialized version for each specialized + * kind that appears in one of the signatures as either the object + * kind (for non-static signature) or the return type (for static + * signatures). + * Note that if an instance occurs where the domain is specialized and + * one where the range is specialized, then an instance where both + * are specialized should also be generated. + * This is not currently guaranteed by the code. + * Instead, the required kind is assumed to be among + * those derived from the signatures of the exported methods. + */ +static void printDefinition( + const std::string& base, + const std::string& className, + const Kind& genericClassKind, + const Exported& exported) { + if (exported.count(base) == 0) { + return; + } + + std::set kinds{genericClassKind}; + collectSpecializedKinds(base, genericClassKind, exported, kinds); + for (auto kind : kinds) { + Subs subs = specializer(kind, genericClassKind); + printOneDefinition(base, className, kind, exported, subs); + } +} + +/* + * Print templated versions of the exported methods for each class and + * for each number of template arguments. + * + * For the most part, the order in which the different specializations + * appear is immaterial. However, a specialization with zero template + * arguments needs to appear before any use, as such a use is otherwise + * considered to refer to an incomplete type. + * Specializations with zero template arguments are therefore printed first. + * Since Space<> is used by Set<>, while Set<> is used by other *<>, + * these two are printed first among those with zero template arguments. + */ +static void printDefinitions(const Exported& exported) { + printDefinition("space", "Space", paramsKind(), exported); + printDefinition("set", "Set", paramsKind(), exported); + for (auto kvp : classes) { + for (auto kind : kvp.second.kinds) { + if (kind.size() == 0 && kvp.first != "space" && kvp.first != "set") { + printDefinition(kvp.first, kvp.second.name, kind, exported); + } + } + } + for (auto kvp : classes) { + for (auto kind : kvp.second.kinds) { + if (kind.size() != 0) { + printDefinition(kvp.first, kvp.second.name, kind, exported); + } + } + } +} + +/* + * Extract the type from a method argument. + * Some of these types are const, while others are not. + */ +static std::string extractType(std::string arg) { + size_t start = 0; + constexpr auto constStr = "const "; + if (arg.find(constStr) == 0) { + start += strlen(constStr); + } + return dropIslNamespace(arg.substr(0, arg.find(" ", start))); +} + +/* + * Rudimentary extraction of argument types from whatever appears + * between the parentheses in a method declaration. + * In particular, split "args" into pieces separated by ", ". + * This does not work properly if any of the arguments + * also contains this sequence, e.g., a function pointer + * to a function with multiple arguments. + */ +static std::vector extractArgumentTypes(const std::string& args) { + std::vector list; + size_t pos, old = 0; + + while ((pos = args.find(", ", old)) != std::string::npos) { + list.emplace_back(extractType(args.substr(old, pos))); + old = pos + 2; + } + if (args.length() > 0) { + list.emplace_back(extractType(args.substr(old))); + } + return list; +} + +/* + * Collect all C++ methods exported by the regular C++ interface + * from standard input for which a kind signature is available. + * For each method called "from" with a single argument, + * a special "#to" method is also added to the class + * corresponding to this single argument. + * Methods that have a names starting with "foreach" are also added. + */ +static void collectExportedFromInput(Exported& exported) { + for (std::string line; std::getline(std::cin, line);) { + // This matches both static and regular methods. + // The static methods do not have a "const" specifier. + std::regex declaration("^([a-z_:]+) (.*)::([a-z_]+)\\((.*)\\)(.*const)?$"); + std::smatch match; + if (!std::regex_match(line, match, declaration)) { + continue; + } + + auto retType = dropIslNamespace(match[1].str()); + auto className = dropIslNamespace(match[2].str()); + auto name = match[3].str(); + auto args = extractArgumentTypes(match[4].str()); + + if (name == "from" && args.size() == 1) { + exported[args[0]].emplace_back(Method{"#to", {retType}}); + } + if (signatures.count(name) == 0 && + specificSignatures.count({className, name}) == 0 && + staticSignatures.count(name) == 0 && + specificStaticSignatures.count({className, name}) == 0 && + !isForeach(name)) { + continue; + } + + exported[className].emplace_back(Method{name, {retType, args}}); + } +} + +/* + * Collect all C++ methods exported by the regular C++ interface, + * for which a kind signature is available. + * For each method called "from" with a single argument, + * a special "#to" method is also added to the class + * corresponding to this single argument. + * + * Additionally, for each hard-coded constructor in "constructors" + * with a single argument, an "#as" method is added to the class + * corresponding to this single argument. + */ +static Exported collectExported() { + Exported exported; + + collectExportedFromInput(exported); + + for (auto kvp : constructors) { + for (const auto& constructor : kvp.second) { + const auto& args = constructor.argTypes; + if (args.size() == 1) { + exported[args[0]].emplace_back(Method{"#as", {kvp.first, args}}); + } + } + } + + return exported; +} + +/* + * Generate a templated isl C++ interface on standard output + * from the regular C++ interface read from standard input. + */ +int main(int argc, char** argv) { + auto exported = collectExported(); + + std::cout << header; + printForwardDeclarations(); + printDefinitions(exported); + std::cout << footer; + + return EXIT_SUCCESS; +} diff --git a/tc/external/detail/islpp.h b/tc/external/detail/islpp.h index 612957080..67dc450a4 100644 --- a/tc/external/detail/islpp.h +++ b/tc/external/detail/islpp.h @@ -252,6 +252,8 @@ struct UnionAsVector } }; +#include + struct IslIdIslHash { size_t operator()(const isl::id& id) const { return isl_id_get_hash(id.get()); From 3336fcb17e48fbcef89541f0ed61066cef30114c Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 18 Jul 2018 15:29:20 +0200 Subject: [PATCH 03/85] inline extractDomainToIds This function will be templated on the mapping type and therefore needs to move to a header file. First move it in its original form to make it easier to see the differences later on. --- tc/core/polyhedral/schedule_utils-inl.h | 76 +++++++++++++++++++++++++ tc/core/polyhedral/schedule_utils.cc | 49 ---------------- tc/core/polyhedral/schedule_utils.h | 2 + 3 files changed, 78 insertions(+), 49 deletions(-) create mode 100644 tc/core/polyhedral/schedule_utils-inl.h diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h new file mode 100644 index 000000000..e1adb7298 --- /dev/null +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2017-2018, Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "tc/core/check.h" +#include "tc/core/polyhedral/schedule_tree.h" +#include "tc/core/polyhedral/schedule_tree_elem.h" +#include "tc/external/isl.h" + +namespace tc { +namespace polyhedral { + +/* + * Extract a mapping from the domain elements active at "tree" + * to identifiers "ids", where all branches in "tree" + * are assumed to have been mapped to these identifiers. + * The result lives in a space of the form "tupleId"["ids"...]. + */ +inline isl::multi_union_pw_aff extractDomainToIds( + const detail::ScheduleTree* root, + const detail::ScheduleTree* tree, + const std::vector& ids, + isl::id tupleId) { + using namespace polyhedral::detail; + + auto space = isl::space(tree->ctx_, 0); + auto empty = isl::union_set::empty(space); + space = space.add_named_tuple_id_ui(tupleId, ids.size()); + auto zero = isl::multi_val::zero(space); + auto domainToIds = isl::multi_union_pw_aff(empty, zero); + + for (auto mapping : tree->collect(tree, ScheduleTreeType::Mapping)) { + auto mappingNode = mapping->as(); + auto list = isl::union_pw_aff_list(tree->ctx_, ids.size()); + for (auto id : ids) { + if (mappingNode->mapping.count(id) == 0) { + break; + } + auto idMap = mappingNode->mapping.at(id); + list = list.add(idMap); + } + // Ignore this node if it does not map to all required ids. + if (static_cast(list.size()) != ids.size()) { + continue; + } + auto nodeToIds = isl::multi_union_pw_aff(space, list); + auto active = activeDomainPoints(root, mapping); + TC_CHECK(active.intersect(domainToIds.domain()).is_empty()) + << "conflicting mappings; are the filters in the tree disjoint?"; + nodeToIds = nodeToIds.intersect_domain(active); + domainToIds = domainToIds.union_add(nodeToIds); + } + + auto active = activeDomainPoints(root, tree); + TC_CHECK(active.is_subset(domainToIds.domain())) + << "not all domain points of\n" + << active << "\nwere mapped to the required ids"; + + return domainToIds; +} + +} // namespace polyhedral +} // namespace tc diff --git a/tc/core/polyhedral/schedule_utils.cc b/tc/core/polyhedral/schedule_utils.cc index 37a1a7d96..618a536f1 100644 --- a/tc/core/polyhedral/schedule_utils.cc +++ b/tc/core/polyhedral/schedule_utils.cc @@ -243,54 +243,5 @@ isl::multi_union_pw_aff partialScheduleMupa( return band ? prefix.flat_range_product(band->mupa_) : prefix; } -/* - * Extract a mapping from the domain elements active at "tree" - * to identifiers "ids", where all branches in "tree" - * are assumed to have been mapped to these identifiers. - * The result lives in a space of the form "tupleId"["ids"...]. - */ -isl::multi_union_pw_aff extractDomainToIds( - const detail::ScheduleTree* root, - const detail::ScheduleTree* tree, - const std::vector& ids, - isl::id tupleId) { - using namespace polyhedral::detail; - - auto space = isl::space(tree->ctx_, 0); - auto empty = isl::union_set::empty(space); - space = space.add_named_tuple_id_ui(tupleId, ids.size()); - auto zero = isl::multi_val::zero(space); - auto domainToIds = isl::multi_union_pw_aff(empty, zero); - - for (auto mapping : tree->collect(tree, ScheduleTreeType::Mapping)) { - auto mappingNode = mapping->as(); - auto list = isl::union_pw_aff_list(tree->ctx_, ids.size()); - for (auto id : ids) { - if (mappingNode->mapping.count(id) == 0) { - break; - } - auto idMap = mappingNode->mapping.at(id); - list = list.add(idMap); - } - // Ignore this node if it does not map to all required ids. - if (static_cast(list.size()) != ids.size()) { - continue; - } - auto nodeToIds = isl::multi_union_pw_aff(space, list); - auto active = activeDomainPoints(root, mapping); - TC_CHECK(active.intersect(domainToIds.domain()).is_empty()) - << "conflicting mappings; are the filters in the tree disjoint?"; - nodeToIds = nodeToIds.intersect_domain(active); - domainToIds = domainToIds.union_add(nodeToIds); - } - - auto active = activeDomainPoints(root, tree); - TC_CHECK(active.is_subset(domainToIds.domain())) - << "not all domain points of\n" - << active << "\nwere mapped to the required ids"; - - return domainToIds; -} - } // namespace polyhedral } // namespace tc diff --git a/tc/core/polyhedral/schedule_utils.h b/tc/core/polyhedral/schedule_utils.h index adca3decf..93bcff92d 100644 --- a/tc/core/polyhedral/schedule_utils.h +++ b/tc/core/polyhedral/schedule_utils.h @@ -140,3 +140,5 @@ bool isMappingTo(const detail::ScheduleTree* tree) { } // namespace polyhedral } // namespace tc + +#include "tc/core/polyhedral/schedule_utils-inl.h" From 621f766343ae430ffe99929cf30f985a7fd82255 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 25 Jul 2018 12:26:49 +0200 Subject: [PATCH 04/85] inline isSingleReductionWithin This function will be templated on the prefix type and therefore needs to move to a header file. First move it in its original form to make it easier to see the differences later on. --- tc/core/polyhedral/reduction_matcher.cc | 11 ----------- tc/core/polyhedral/schedule_tree_matcher-inl.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tc/core/polyhedral/reduction_matcher.cc b/tc/core/polyhedral/reduction_matcher.cc index 8b21f4023..59aeaf13f 100644 --- a/tc/core/polyhedral/reduction_matcher.cc +++ b/tc/core/polyhedral/reduction_matcher.cc @@ -66,16 +66,5 @@ isl::union_set reductionUpdates(isl::union_set domain, const Scop& scop) { return update; } -bool isSingleReductionWithin( - isl::union_set domain, - isl::multi_union_pw_aff prefix, - const Scop& scop) { - auto reductions = scop.body.reductions; - reductions = reductions.intersect_domain(domain); - auto prefixMap = isl::union_map::from(prefix); - auto prefixToReduction = reductions.apply_domain(prefixMap); - return prefixToReduction.is_single_valued(); -} - } // namespace polyhedral } // namespace tc diff --git a/tc/core/polyhedral/schedule_tree_matcher-inl.h b/tc/core/polyhedral/schedule_tree_matcher-inl.h index 41a4ba434..8a2b2196c 100644 --- a/tc/core/polyhedral/schedule_tree_matcher-inl.h +++ b/tc/core/polyhedral/schedule_tree_matcher-inl.h @@ -291,5 +291,16 @@ inline std::vector match( return matchDFSPreorder(matcher, tree); } +inline bool isSingleReductionWithin( + isl::union_set domain, + isl::multi_union_pw_aff prefix, + const Scop& scop) { + auto reductions = scop.body.reductions; + reductions = reductions.intersect_domain(domain); + auto prefixMap = isl::union_map::from(prefix); + auto prefixToReduction = reductions.apply_domain(prefixMap); + return prefixToReduction.is_single_valued(); +} + } // namespace polyhedral } // namespace tc From 78ffa1d314ec2990e0fcb039eacd6cd51f692f55 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 25 Jul 2018 16:29:04 +0200 Subject: [PATCH 05/85] inline ScheduleTreeBand::memberRange This function will be templated on the target type and therefore needs to move to a header file. First move it in its original form to make it easier to see the differences later on. --- tc/core/polyhedral/schedule_tree_elem.cc | 11 ----------- tc/core/polyhedral/schedule_tree_elem.h | 10 +++++++++- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/tc/core/polyhedral/schedule_tree_elem.cc b/tc/core/polyhedral/schedule_tree_elem.cc index 816df26f8..1e9584005 100644 --- a/tc/core/polyhedral/schedule_tree_elem.cc +++ b/tc/core/polyhedral/schedule_tree_elem.cc @@ -248,17 +248,6 @@ void ScheduleTreeBand::drop(size_t pos, size_t n) { TC_CHECK_EQ(nBegin - n, nMember()); } -isl::multi_union_pw_aff ScheduleTreeBand::memberRange(size_t first, size_t n) - const { - auto list = mupa_.get_union_pw_aff_list(); - auto space = mupa_.get_space().params().add_unnamed_tuple_ui(n); - auto end = first + n; - TC_CHECK_LE(end, nMember()); - list = list.drop(end, nMember() - end); - list = list.drop(0, first); - return isl::multi_union_pw_aff(space, list); -} - std::unique_ptr ScheduleTreeThreadSpecificMarker::make( isl::ctx ctx, diff --git a/tc/core/polyhedral/schedule_tree_elem.h b/tc/core/polyhedral/schedule_tree_elem.h index 5d782049d..91cc61444 100644 --- a/tc/core/polyhedral/schedule_tree_elem.h +++ b/tc/core/polyhedral/schedule_tree_elem.h @@ -331,7 +331,15 @@ struct ScheduleTreeBand : public ScheduleTree { // Extract the range of "n" members starting at "first" // (in an anonymous space). - isl::multi_union_pw_aff memberRange(size_t first, size_t n) const; + isl::multi_union_pw_aff memberRange(size_t first, size_t n) const { + auto list = mupa_.get_union_pw_aff_list(); + auto space = mupa_.get_space().params().add_unnamed_tuple_ui(n); + auto end = first + n; + TC_CHECK_LE(end, nMember()); + list = list.drop(end, nMember() - end); + list = list.drop(0, first); + return isl::multi_union_pw_aff(space, list); + } public: bool permutable_{false}; From 7de5f5b77ed13d3dd0a22ffe9b555457e271f53e Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 1 Aug 2018 09:36:16 +0200 Subject: [PATCH 06/85] inline partialScheduleMupa This function will be templated on the schedule type and therefore needs to move to a header file. First move it in its original form (with an extra "using") to make it easier to see the differences later on. --- tc/core/polyhedral/schedule_utils-inl.h | 10 ++++++++++ tc/core/polyhedral/schedule_utils.cc | 8 -------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index e1adb7298..a50a50346 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -23,6 +23,16 @@ namespace tc { namespace polyhedral { +inline isl::multi_union_pw_aff partialScheduleMupa( + const detail::ScheduleTree* root, + const detail::ScheduleTree* tree) { + using namespace polyhedral::detail; + + auto prefix = prefixScheduleMupa(root, tree); + auto band = tree->as(); + return band ? prefix.flat_range_product(band->mupa_) : prefix; +} + /* * Extract a mapping from the domain elements active at "tree" * to identifiers "ids", where all branches in "tree" diff --git a/tc/core/polyhedral/schedule_utils.cc b/tc/core/polyhedral/schedule_utils.cc index 618a536f1..82ec9fac0 100644 --- a/tc/core/polyhedral/schedule_utils.cc +++ b/tc/core/polyhedral/schedule_utils.cc @@ -235,13 +235,5 @@ isl::multi_union_pw_aff prefixScheduleMupa( return infixScheduleMupa(root, root, tree); } -isl::multi_union_pw_aff partialScheduleMupa( - const detail::ScheduleTree* root, - const detail::ScheduleTree* tree) { - auto prefix = prefixScheduleMupa(root, tree); - auto band = tree->as(); - return band ? prefix.flat_range_product(band->mupa_) : prefix; -} - } // namespace polyhedral } // namespace tc From 61adb7aef03a6579b5247593cc6c748e0293a238 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 1 Aug 2018 09:39:13 +0200 Subject: [PATCH 07/85] inline prefixScheduleMupa This function will be templated on the schedule type and therefore needs to move to a header file. First move it in its original form to make it easier to see the differences later on. --- tc/core/polyhedral/schedule_utils-inl.h | 6 ++++++ tc/core/polyhedral/schedule_utils.cc | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index a50a50346..1f4bd7b22 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -23,6 +23,12 @@ namespace tc { namespace polyhedral { +inline isl::multi_union_pw_aff prefixScheduleMupa( + const detail::ScheduleTree* root, + const detail::ScheduleTree* tree) { + return infixScheduleMupa(root, root, tree); +} + inline isl::multi_union_pw_aff partialScheduleMupa( const detail::ScheduleTree* root, const detail::ScheduleTree* tree) { diff --git a/tc/core/polyhedral/schedule_utils.cc b/tc/core/polyhedral/schedule_utils.cc index 82ec9fac0..fb5f38d1d 100644 --- a/tc/core/polyhedral/schedule_utils.cc +++ b/tc/core/polyhedral/schedule_utils.cc @@ -229,11 +229,5 @@ isl::multi_union_pw_aff infixScheduleMupa( return prefix; } -isl::multi_union_pw_aff prefixScheduleMupa( - const ScheduleTree* root, - const ScheduleTree* tree) { - return infixScheduleMupa(root, root, tree); -} - } // namespace polyhedral } // namespace tc From bff837894dbd8f692ee2c396c6afd2b62c437379 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 1 Aug 2018 09:44:30 +0200 Subject: [PATCH 08/85] inline infixScheduleMupa This function will be templated on the schedule type and therefore needs to move to a header file. First move it in its original form (with an extra "using") to make it easier to see the differences later on. --- tc/core/polyhedral/schedule_utils-inl.h | 49 +++++++++++++++++++++++++ tc/core/polyhedral/schedule_utils.cc | 43 ---------------------- 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index 1f4bd7b22..0e6305799 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -15,6 +15,8 @@ */ #pragma once +#include + #include "tc/core/check.h" #include "tc/core/polyhedral/schedule_tree.h" #include "tc/core/polyhedral/schedule_tree_elem.h" @@ -23,6 +25,53 @@ namespace tc { namespace polyhedral { +namespace detail { + +template +inline std::vector filterType( + const std::vector& vec) { + std::vector result; + for (auto e : vec) { + if (e->as()) { + result.push_back(e); + } + } + return result; +} + +template +inline T +foldl(const std::vector vec, Func op, T init = T()) { + T value = init; + for (auto st : vec) { + value = op(st, value); + } + return value; +} + +} // namespace detail + +inline isl::multi_union_pw_aff infixScheduleMupa( + const detail::ScheduleTree* root, + const detail::ScheduleTree* relativeRoot, + const detail::ScheduleTree* tree) { + using namespace polyhedral::detail; + + auto domainElem = root->as(); + TC_CHECK(domainElem); + auto domain = domainElem->domain_.universe(); + auto zero = isl::multi_val::zero(domain.get_space().set_from_params()); + auto prefix = isl::multi_union_pw_aff(domain, zero); + prefix = foldl( + filterType(tree->ancestors(relativeRoot)), + [](const ScheduleTree* st, isl::multi_union_pw_aff pref) { + auto mupa = st->as()->mupa_; + return pref.flat_range_product(mupa); + }, + prefix); + return prefix; +} + inline isl::multi_union_pw_aff prefixScheduleMupa( const detail::ScheduleTree* root, const detail::ScheduleTree* tree) { diff --git a/tc/core/polyhedral/schedule_utils.cc b/tc/core/polyhedral/schedule_utils.cc index fb5f38d1d..1f82bfaab 100644 --- a/tc/core/polyhedral/schedule_utils.cc +++ b/tc/core/polyhedral/schedule_utils.cc @@ -186,48 +186,5 @@ vector collectScheduleTreesPath( return res; } -namespace { - -template -vector filterType(const vector& vec) { - vector result; - for (auto e : vec) { - if (e->as()) { - result.push_back(e); - } - } - return result; -} - -template -T foldl(const vector vec, Func op, T init = T()) { - T value = init; - for (auto st : vec) { - value = op(st, value); - } - return value; -} - -} // namespace - -isl::multi_union_pw_aff infixScheduleMupa( - const ScheduleTree* root, - const ScheduleTree* relativeRoot, - const ScheduleTree* tree) { - auto domainElem = root->as(); - TC_CHECK(domainElem); - auto domain = domainElem->domain_.universe(); - auto zero = isl::multi_val::zero(domain.get_space().set_from_params()); - auto prefix = isl::multi_union_pw_aff(domain, zero); - prefix = foldl( - filterType(tree->ancestors(relativeRoot)), - [](const ScheduleTree* st, isl::multi_union_pw_aff pref) { - auto mupa = st->as()->mupa_; - return pref.flat_range_product(mupa); - }, - prefix); - return prefix; -} - } // namespace polyhedral } // namespace tc From f188f2ce0671787556a0bbb6f3671cfb69e6e7d7 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 1 Aug 2018 10:47:55 +0200 Subject: [PATCH 09/85] inline prefixSchedule and partialSchedule These functions will be templated on the schedule type and therefore need to move to a header file. First move them in their original form to make it easier to see the differences later on. --- tc/core/polyhedral/schedule_utils-inl.h | 36 +++++++++++++++++++++++++ tc/core/polyhedral/schedule_utils.cc | 36 ------------------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index 0e6305799..1be023d59 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -25,6 +25,42 @@ namespace tc { namespace polyhedral { +namespace detail { +inline isl::union_map partialScheduleImpl( + const ScheduleTree* root, + const ScheduleTree* node, + bool useNode) { + auto nodes = node->ancestors(root); + if (useNode) { + nodes.push_back(node); + } + TC_CHECK_GT(nodes.size(), 0u) << "root node does not have a prefix schedule"; + auto domain = root->as(); + TC_CHECK(domain); + auto schedule = isl::union_map::from_domain(domain->domain_); + for (auto anc : nodes) { + if (anc->as()) { + TC_CHECK(anc == root); + } else { + schedule = extendSchedule(anc, schedule); + } + } + return schedule; +} +} // namespace detail + +inline isl::union_map prefixSchedule( + const detail::ScheduleTree* root, + const detail::ScheduleTree* node) { + return detail::partialScheduleImpl(root, node, false); +} + +inline isl::union_map partialSchedule( + const detail::ScheduleTree* root, + const detail::ScheduleTree* node) { + return detail::partialScheduleImpl(root, node, true); +} + namespace detail { template diff --git a/tc/core/polyhedral/schedule_utils.cc b/tc/core/polyhedral/schedule_utils.cc index 1f82bfaab..4622bf45c 100644 --- a/tc/core/polyhedral/schedule_utils.cc +++ b/tc/core/polyhedral/schedule_utils.cc @@ -49,42 +49,6 @@ isl::union_map extendSchedule( return schedule; } -namespace { -isl::union_map partialScheduleImpl( - const ScheduleTree* root, - const ScheduleTree* node, - bool useNode) { - auto nodes = node->ancestors(root); - if (useNode) { - nodes.push_back(node); - } - TC_CHECK_GT(nodes.size(), 0u) << "root node does not have a prefix schedule"; - auto domain = root->as(); - TC_CHECK(domain); - auto schedule = isl::union_map::from_domain(domain->domain_); - for (auto anc : nodes) { - if (anc->as()) { - TC_CHECK(anc == root); - } else { - schedule = extendSchedule(anc, schedule); - } - } - return schedule; -} -} // namespace - -isl::union_map prefixSchedule( - const ScheduleTree* root, - const ScheduleTree* node) { - return partialScheduleImpl(root, node, false); -} - -isl::union_map partialSchedule( - const ScheduleTree* root, - const ScheduleTree* node) { - return partialScheduleImpl(root, node, true); -} - namespace { /* * If "node" is any filter, then intersect "domain" with that filter. From 012737e2cdcc62a9944148224ec6662abe794c08 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 2 Aug 2018 10:39:36 +0200 Subject: [PATCH 10/85] inline extendSchedule This function will be templated on the schedule type and therefore needs to move to a header file. First move it in its original form (with an extra "using") to make it easier to see the differences later on. --- tc/core/polyhedral/schedule_utils-inl.h | 23 +++++++++++++++++++++++ tc/core/polyhedral/schedule_utils.cc | 21 --------------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index 1be023d59..3c6be4645 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -25,6 +25,29 @@ namespace tc { namespace polyhedral { +inline isl::union_map extendSchedule( + const detail::ScheduleTree* node, + isl::union_map schedule) { + using namespace polyhedral::detail; + + if (auto bandElem = node->as()) { + if (bandElem->nMember() > 0) { + schedule = + schedule.flat_range_product(isl::union_map::from(bandElem->mupa_)); + } + } else if (auto filterElem = node->as()) { + schedule = schedule.intersect_domain(filterElem->filter_); + } else if (auto extensionElem = node->as()) { + // FIXME: we may need to restrict the range of reversed extension map to + // schedule values that correspond to active domain elements at this + // point. + schedule = schedule.unite( + extensionElem->extension_.reverse().intersect_range(schedule.range())); + } + + return schedule; +} + namespace detail { inline isl::union_map partialScheduleImpl( const ScheduleTree* root, diff --git a/tc/core/polyhedral/schedule_utils.cc b/tc/core/polyhedral/schedule_utils.cc index 4622bf45c..1b5da0dfe 100644 --- a/tc/core/polyhedral/schedule_utils.cc +++ b/tc/core/polyhedral/schedule_utils.cc @@ -28,27 +28,6 @@ using namespace detail; using std::ostream; using std::vector; -isl::union_map extendSchedule( - const ScheduleTree* node, - isl::union_map schedule) { - if (auto bandElem = node->as()) { - if (bandElem->nMember() > 0) { - schedule = - schedule.flat_range_product(isl::union_map::from(bandElem->mupa_)); - } - } else if (auto filterElem = node->as()) { - schedule = schedule.intersect_domain(filterElem->filter_); - } else if (auto extensionElem = node->as()) { - // FIXME: we may need to restrict the range of reversed extension map to - // schedule values that correspond to active domain elements at this - // point. - schedule = schedule.unite( - extensionElem->extension_.reverse().intersect_range(schedule.range())); - } - - return schedule; -} - namespace { /* * If "node" is any filter, then intersect "domain" with that filter. From fecceb29f17ebe99c5cfdb3e3e27840ec1cf05af Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 11/85] halide2isl.cc: extractAccess: explicitly cast space to isl::Space<> This will make it easier to gradually introduce the use of templated isl types by breaking a cycle. The explicit cast will be removed again after the core halide2isl has been converted to templated isl types. --- tc/core/halide2isl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/core/halide2isl.cc b/tc/core/halide2isl.cc index cb46434ba..e166141ba 100644 --- a/tc/core/halide2isl.cc +++ b/tc/core/halide2isl.cc @@ -258,7 +258,7 @@ isl::map extractAccess( // to the outer loop iterators) and then convert this set // into a map in terms of the iteration domain. - isl::space paramSpace = domain.paramSpace; + auto paramSpace = isl::Space<>(domain.paramSpace); isl::id tensorID(paramSpace.get_ctx(), tensor); auto tensorTuple = constructTensorTuple(paramSpace, tensorID, args.size()); auto tensorSpace = tensorTuple.get_space(); From 679083118b4c10934040062c85347a26bbb99a4f Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 12/85] memory_promotion.cc: tensorElementsSet: explicitly cast space to isl::Space<> This will make it easier to gradually introduce the use of templated isl types by breaking a cycle. The explicit cast will be removed again after Scop::Domain() has been converted to templated isl types. --- tc/core/polyhedral/memory_promotion.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index 37656f09a..324dc6efd 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -410,7 +410,7 @@ namespace { // context of the scop. isl::set tensorElementsSet(const Scop& scop, isl::id tensorId) { auto halideParameter = scop.findArgument(tensorId).parameter(); - auto space = scop.domain().get_space(); + auto space = isl::Space<>(scop.domain().get_space()); auto nDim = halideParameter.dimensions(); auto tensorTuple = constructTensorTuple(space, tensorId, nDim); auto tensorSpace = tensorTuple.get_space(); From fc8fb131eb15791306ca1fd1f5ecc506f5163cff Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 13/85] constructTensorTuple: use templated isl types --- tc/core/polyhedral/domain_types.h | 7 +++++++ tc/core/polyhedral/utils.cc | 10 ++++++---- tc/core/polyhedral/utils.h | 5 +++-- 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 tc/core/polyhedral/domain_types.h diff --git a/tc/core/polyhedral/domain_types.h b/tc/core/polyhedral/domain_types.h new file mode 100644 index 000000000..ed15b2fcb --- /dev/null +++ b/tc/core/polyhedral/domain_types.h @@ -0,0 +1,7 @@ +namespace tc { +namespace polyhedral { + +struct Tensor; + +} // namespace polyhedral +} // namespace tc diff --git a/tc/core/polyhedral/utils.cc b/tc/core/polyhedral/utils.cc index 80cf11f78..07e1b83ee 100644 --- a/tc/core/polyhedral/utils.cc +++ b/tc/core/polyhedral/utils.cc @@ -15,6 +15,8 @@ */ #include "tc/core/polyhedral/utils.h" +#include "tc/core/polyhedral/domain_types.h" + namespace tc { namespace polyhedral { @@ -24,15 +26,15 @@ namespace polyhedral { * of the user. * Since some names are required, use names of the form "__tc_tensor_arg*". */ -isl::multi_id -constructTensorTuple(isl::space paramSpace, isl::id tensorId, size_t dim) { - auto tensorSpace = paramSpace.add_named_tuple_id_ui(tensorId, dim); +isl::MultiId +constructTensorTuple(isl::Space<> paramSpace, isl::id tensorId, size_t dim) { + auto tensorSpace = paramSpace.add_named_tuple_id_ui(tensorId, dim); isl::id_list tensorArgs(paramSpace.get_ctx(), 0); for (size_t i = 0; i < dim; ++i) { auto name = std::string("__tc_tensor_arg") + std::to_string(i); tensorArgs = tensorArgs.add(isl::id(paramSpace.get_ctx(), name)); } - return isl::multi_id(tensorSpace, tensorArgs); + return isl::MultiId(tensorSpace, tensorArgs); } } // namespace polyhedral diff --git a/tc/core/polyhedral/utils.h b/tc/core/polyhedral/utils.h index 459bca648..31512f9f3 100644 --- a/tc/core/polyhedral/utils.h +++ b/tc/core/polyhedral/utils.h @@ -15,6 +15,7 @@ */ #pragma once +#include "tc/core/polyhedral/domain_types.h" #include "tc/external/isl.h" namespace tc { @@ -24,8 +25,8 @@ namespace polyhedral { * dimension "dim" from the parameter space "paramSpace", * without any specific names for the indices. */ -isl::multi_id -constructTensorTuple(isl::space paramSpace, isl::id tensorId, size_t dim); +isl::MultiId +constructTensorTuple(isl::Space<> paramSpace, isl::id tensorId, size_t dim); } // namespace polyhedral } // namespace tc From 0cb8fb2e1d6c26d63f7b259cc962516b6b1ce61d Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 14/85] Scop::makeContext: explicitly cast space to isl::Space<> This will make it easier to gradually introduce the use of templated isl types by breaking a cycle. The explicit cast will be removed again after Scop::Domain() has been converted to templated isl types. --- tc/core/polyhedral/scop.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/core/polyhedral/scop.h b/tc/core/polyhedral/scop.h index b8d9c7982..06c55b8cb 100644 --- a/tc/core/polyhedral/scop.h +++ b/tc/core/polyhedral/scop.h @@ -136,7 +136,7 @@ struct Scop { isl::set makeContext( const std::unordered_map& sizes = std::unordered_map()) const { - auto s = domain().get_space(); + auto s = isl::Space<>(domain().get_space()); return makeSpecializationSet(s, sizes); } From e4d6e0c584ffc5a4f9963097152afab7a16198c7 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 15/85] makeSpecializationSet: use templated isl types Use explicit API calls instead of operators because the use of aff_set is confusing (at least to the author of this commit). The conversion to an isl::PwAff is needed because, unlike the Python bindings, the C++ bindings do not have a class hierarchy. The conversion could also be avoided by introducing an isl_aff_zero_set in isl. --- tc/external/detail/islpp.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tc/external/detail/islpp.h b/tc/external/detail/islpp.h index 67dc450a4..1d730d6b7 100644 --- a/tc/external/detail/islpp.h +++ b/tc/external/detail/islpp.h @@ -310,18 +310,18 @@ inline isl::set makeParameterContext( // that ties the space parameter to the values. // template -inline isl::set makeSpecializationSet( - isl::space space, +inline isl::Set<> makeSpecializationSet( + isl::Space<> space, const std::unordered_map& paramValues) { auto ctx = space.get_ctx(); for (auto kvp : paramValues) { space = space.add_param(isl::id(ctx, kvp.first)); } - auto set = isl::set::universe(space); + auto set = isl::Set<>::universe(space); for (auto kvp : paramValues) { auto id = isl::id(ctx, kvp.first); - isl::aff affParam(isl::aff::param_on_domain_space(space, id)); - set = set & (isl::aff_set(affParam) == kvp.second); + auto affParam(isl::AffOn<>::param_on_domain_space(space, id)); + set = set & (affParam - kvp.second).asPwAff().zero_set(); } return set; } From d842f1130c516973e1b4e8e3bd6798024c421ae0 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 16/85] Scop::makeContext: use templated isl types --- tc/core/polyhedral/scop.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/core/polyhedral/scop.h b/tc/core/polyhedral/scop.h index 06c55b8cb..0e574ad50 100644 --- a/tc/core/polyhedral/scop.h +++ b/tc/core/polyhedral/scop.h @@ -133,7 +133,7 @@ struct Scop { // Returns a set that specializes the named scop's subset of // parameter space to the integer values passed to the function. template - isl::set makeContext( + isl::Set<> makeContext( const std::unordered_map& sizes = std::unordered_map()) const { auto s = isl::Space<>(domain().get_space()); From fec4a87911decce986157504edfb756314d43139 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 17/85] Scop::context(): use templated isl types --- tc/core/polyhedral/cuda/mapped_scop.cc | 3 ++- tc/core/polyhedral/domain_types.h | 1 + tc/core/polyhedral/scop.h | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index 930c92aa3..eb555d94f 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -32,6 +32,7 @@ #include "tc/core/polyhedral/cuda/mapping_types.h" #include "tc/core/polyhedral/cuda/memory_promotion_heuristic.h" #include "tc/core/polyhedral/cuda/tighten_launch_bounds.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/exceptions.h" #include "tc/core/polyhedral/schedule_transforms.h" #include "tc/core/polyhedral/schedule_tree_matcher.h" @@ -895,7 +896,7 @@ std::unique_ptr makeSpecializedMappedScop( // outer schedule dimensions, so the space of a parameter context code is that // of a zero-dimensional space. auto root = scop->scheduleRoot(); - updateTopLevelContext(root, scop->context().from_params()); + updateTopLevelContext(root, scop->context().from_params()); tc::Grid grid = mappedScop.numBlocks; tc::Block block = mappedScop.numThreads; diff --git a/tc/core/polyhedral/domain_types.h b/tc/core/polyhedral/domain_types.h index ed15b2fcb..96b740bd2 100644 --- a/tc/core/polyhedral/domain_types.h +++ b/tc/core/polyhedral/domain_types.h @@ -1,6 +1,7 @@ namespace tc { namespace polyhedral { +struct Prefix; struct Tensor; } // namespace polyhedral diff --git a/tc/core/polyhedral/scop.h b/tc/core/polyhedral/scop.h index 0e574ad50..b59e8bb20 100644 --- a/tc/core/polyhedral/scop.h +++ b/tc/core/polyhedral/scop.h @@ -94,10 +94,10 @@ struct Scop { // The schedule tree of the scop does not necessarily have // a context node. Call updateTopLevelContext on the schedule tree // to introduce or refine such a context node. - isl::set context() const { + isl::Set<> context() const { auto ctx = domain().get_ctx(); auto context = halide2isl::makeParamContext(ctx, halide.params); - return context.intersect(makeContext(parameterValues)); + return isl::Set<>(context.intersect(makeContext(parameterValues))); } // Specialize a Scop by fixing the given parameters to the given sizes. From 8e32a037df973c0cfcc37c2846286773c1f1ecad Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 18/85] codegen_llvm.cc: getTensorSize: use templated isl types --- tc/core/polyhedral/codegen_llvm.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tc/core/polyhedral/codegen_llvm.cc b/tc/core/polyhedral/codegen_llvm.cc index c87289d1f..2942b7ff7 100644 --- a/tc/core/polyhedral/codegen_llvm.cc +++ b/tc/core/polyhedral/codegen_llvm.cc @@ -70,7 +70,7 @@ int64_t toSInt(isl::val v) { return v.get_num_si(); } -int64_t getTensorSize(isl::set context, const Halide::Expr& e) { +int64_t getTensorSize(isl::Set<> context, const Halide::Expr& e) { // isl will take care of substituting parameter values if they are known and // simplifying the expression. auto aff = halide2isl::makeIslAffFromExpr(context.get_space(), e); @@ -81,7 +81,7 @@ int64_t getTensorSize(isl::set context, const Halide::Expr& e) { std::vector getTensorSizesWithoutLeadingDim( const Halide::OutputImageParam& t, - isl::set context) { + isl::Set<> context) { auto dims = t.dimensions(); std::vector sizes; sizes.reserve(dims); From d1b2729cd36af97b41cb6b12ed7139c1164fc675 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 25 Jul 2018 09:52:11 +0200 Subject: [PATCH 19/85] memory_promotion.cc: tensorElementsSet: temporarily remove type deduction This allows halide2isl::makeIslAffFromExpr to be converted to templated isl types without having to convert tensorElementsSet at the same time. Automatic type deduction will be reintroduced when tensorElementsSet is converted. --- tc/core/polyhedral/memory_promotion.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index 324dc6efd..1cacd0e7b 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -418,9 +418,9 @@ isl::set tensorElementsSet(const Scop& scop, isl::id tensorId) { auto tensorElements = isl::set::universe(tensorSpace); auto identity = isl::multi_aff::identity(tensorSpace.map_from_set()); for (int i = 0; i < nDim; ++i) { - auto minAff = halide2isl::makeIslAffFromExpr( + isl::aff minAff = halide2isl::makeIslAffFromExpr( space, halideParameter.min_constraint(i)); - auto extentAff = halide2isl::makeIslAffFromExpr( + isl::aff extentAff = halide2isl::makeIslAffFromExpr( space, halideParameter.extent_constraint(i)); minAff = minAff.unbind_params_insert_domain(tensorTuple); extentAff = extentAff.unbind_params_insert_domain(tensorTuple); From 3931595e6f8239b52fddc2a561978fe7e9532005 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 25 Jul 2018 09:52:18 +0200 Subject: [PATCH 20/85] Scop::makeIslAffFromStmtExpr: temporarily remove type deduction This allows halide2isl::makeIslAffFromExpr to be converted to templated isl types without having to convert Scop::makeIslAffFromStmtExpr at the same time. Automatic type deduction will be reintroduced when Scop::makeIslAffFromStmtExpr is converted. --- tc/core/polyhedral/scop.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/core/polyhedral/scop.cc b/tc/core/polyhedral/scop.cc index 41cc17448..5edb94455 100644 --- a/tc/core/polyhedral/scop.cc +++ b/tc/core/polyhedral/scop.cc @@ -518,7 +518,7 @@ const Halide::OutputImageParam& Scop::findArgument(isl::id id) const { isl::aff Scop::makeIslAffFromStmtExpr(isl::id stmtId, const Halide::Expr& e) const { auto domain = halide.domains.at(stmtId); - auto aff = halide2isl::makeIslAffFromExpr(domain.paramSpace, e); + isl::aff aff = halide2isl::makeIslAffFromExpr(domain.paramSpace, e); aff = aff.unbind_params_insert_domain(domain.tuple); return aff; } From aaa920b7b90141101b1e3fcca69e2f1c65a74df5 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 21/85] core halide2isl: use templated isl types --- tc/core/halide2isl.cc | 130 +++++++++++++++++------------- tc/core/halide2isl.h | 15 ++-- tc/core/polyhedral/domain_types.h | 3 + 3 files changed, 85 insertions(+), 63 deletions(-) diff --git a/tc/core/halide2isl.cc b/tc/core/halide2isl.cc index e166141ba..912231fae 100644 --- a/tc/core/halide2isl.cc +++ b/tc/core/halide2isl.cc @@ -21,6 +21,7 @@ #include "tc/core/check.h" #include "tc/core/constants.h" #include "tc/core/polyhedral/body.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_isl_conversion.h" #include "tc/core/polyhedral/schedule_transforms.h" #include "tc/core/polyhedral/schedule_tree.h" @@ -80,13 +81,13 @@ SymbolTable makeSymbolTable(const tc2halide::HalideComponents& components) { return builder.table; } -isl::aff makeIslAffFromInt(isl::space space, int64_t val) { +isl::AffOn<> makeIslAffFromInt(isl::Space<> space, int64_t val) { isl::val v = isl::val(space.get_ctx(), val); - return isl::aff(isl::local_space(space), v); + return isl::AffOn<>(isl::aff(isl::local_space(space), v)); } -std::vector makeIslAffBoundsFromExpr( - isl::space space, +std::vector> makeIslAffBoundsFromExpr( + isl::Space<> space, const Expr& e, bool allowMin, bool allowMax); @@ -101,9 +102,9 @@ namespace { * x > max(a,max(b,c)) <=> x > a AND x > b AND x > c */ template -inline std::vector -concatAffs(isl::space space, T op, bool allowMin, bool allowMax) { - std::vector result; +inline std::vector> +concatAffs(isl::Space<> space, T op, bool allowMin, bool allowMax) { + std::vector> result; for (const auto& aff : makeIslAffBoundsFromExpr(space, op->a, allowMin, allowMax)) { @@ -129,10 +130,10 @@ concatAffs(isl::space space, T op, bool allowMin, bool allowMax) { * x < a + max(b,c) NOT <=> x < a + b AND x < a + c for negative values. */ template -inline std::vector combineSingleAffs( - isl::space space, +inline std::vector> combineSingleAffs( + isl::Space<> space, T op, - isl::aff (isl::aff::*combine)(isl::aff) const) { + isl::AffOn<> (isl::AffOn<>::*combine)(const isl::AffOn<>&) const) { auto left = makeIslAffBoundsFromExpr(space, op->a, false, false); auto right = makeIslAffBoundsFromExpr(space, op->b, false, false); TC_CHECK_LE(left.size(), 1u); @@ -162,8 +163,8 @@ inline std::vector combineSingleAffs( * If a Halide expression cannot be converted into a list of affine expressions, * return an empty list. */ -std::vector makeIslAffBoundsFromExpr( - isl::space space, +std::vector> makeIslAffBoundsFromExpr( + isl::Space<> space, const Expr& e, bool allowMin, bool allowMax) { @@ -178,7 +179,7 @@ std::vector makeIslAffBoundsFromExpr( if (const Variable* op = e.as()) { isl::id id(space.get_ctx(), op->name); if (space.has_param(id)) { - return {isl::aff::param_on_domain_space(space, id)}; + return {isl::AffOn<>::param_on_domain_space(space, id)}; } LOG(FATAL) << "Variable not found in isl::space: " << space << ": " << op << ": " << op->name << '\n'; @@ -188,13 +189,13 @@ std::vector makeIslAffBoundsFromExpr( } else if (maxOp != nullptr && allowMax) { return concatAffs(space, maxOp, allowMin, allowMax); } else if (const Add* op = e.as()) { - return combineSingleAffs(space, op, &isl::aff::add); + return combineSingleAffs(space, op, &isl::AffOn<>::add); } else if (const Sub* op = e.as()) { - return combineSingleAffs(space, op, &isl::aff::sub); + return combineSingleAffs(space, op, &isl::AffOn<>::sub); } else if (const Mul* op = e.as()) { - return combineSingleAffs(space, op, &isl::aff::mul); + return combineSingleAffs(space, op, &isl::AffOn<>::mul); } else if (const Div* op = e.as
()) { - return combineSingleAffs(space, op, &isl::aff::div); + return combineSingleAffs(space, op, &isl::AffOn<>::div); } else if (const Mod* op = e.as()) { std::vector result; // We cannot span multiple constraints if a modulo operation is involved. @@ -211,7 +212,7 @@ std::vector makeIslAffBoundsFromExpr( return {}; } -isl::aff makeIslAffFromExpr(isl::space space, const Expr& e) { +isl::AffOn<> makeIslAffFromExpr(isl::Space<> space, const Expr& e) { auto list = makeIslAffBoundsFromExpr(space, e, false, false); TC_CHECK_LE(list.size(), 1u) << "Halide expr " << e << " unrolled into more than 1 isl aff" @@ -219,13 +220,13 @@ isl::aff makeIslAffFromExpr(isl::space space, const Expr& e) { // Non-affine if (list.size() == 0) { - return isl::aff(); + return isl::AffOn<>(); } return list[0]; } -isl::space makeParamSpace(isl::ctx ctx, const ParameterVector& params) { - auto space = isl::space(ctx, 0); +isl::Space<> makeParamSpace(isl::ctx ctx, const ParameterVector& params) { + auto space = isl::Space<>(ctx, 0); // set parameter names for (auto p : params) { space = space.add_param(isl::id(ctx, p.name())); @@ -233,19 +234,29 @@ isl::space makeParamSpace(isl::ctx ctx, const ParameterVector& params) { return space; } -isl::set makeParamContext(isl::ctx ctx, const ParameterVector& params) { +isl::Set<> makeParamContext(isl::ctx ctx, const ParameterVector& params) { auto space = makeParamSpace(ctx, params); - auto context = isl::set::universe(space); + auto context = isl::Set<>::universe(space); for (auto p : params) { - isl::aff a(isl::aff::param_on_domain_space(space, isl::id(ctx, p.name()))); - context = context & (a >= 0); + auto a(isl::AffOn<>::param_on_domain_space(space, isl::id(ctx, p.name()))); + context = context & a.asPwAff().nonneg_set(); } return context; } namespace { -isl::map extractAccess( +/* + * Call the domain_map factory method of the isl::MultiAff + * with appropriate template arguments. + */ +template +static isl::MultiAff, Domain> domainMap( + isl::Space space) { + return isl::MultiAff, Domain>::domain_map(space); +} + +isl::Map, Tensor> extractAccess( const IterationDomain& domain, const IRNode* op, const std::string& tensor, @@ -258,16 +269,17 @@ isl::map extractAccess( // to the outer loop iterators) and then convert this set // into a map in terms of the iteration domain. - auto paramSpace = isl::Space<>(domain.paramSpace); + auto paramSpace = domain.paramSpace; isl::id tensorID(paramSpace.get_ctx(), tensor); auto tensorTuple = constructTensorTuple(paramSpace, tensorID, args.size()); auto tensorSpace = tensorTuple.get_space(); // Start with a totally unconstrained set - every point in // the allocation could be accessed. - isl::set access = isl::set::universe(tensorSpace); + auto access = isl::Set::universe(tensorSpace); - auto identity = isl::multi_aff::identity(tensorSpace.map_from_set()); + auto identity = + isl::MultiAff::identity(tensorSpace.map_from_set()); for (size_t i = 0; i < args.size(); i++) { // Then add one equality constraint per dimension to encode the // point in the allocation actually read/written for each point in @@ -277,9 +289,9 @@ isl::map extractAccess( // The coordinate written to in the range ... auto rangePoint = identity.get_aff(i); // ... equals the coordinate accessed as a function of the parameters. - auto domainPoint = halide2isl::makeIslAffFromExpr(paramSpace, args[i]); - if (!domainPoint.is_null()) { - domainPoint = domainPoint.unbind_params_insert_domain(tensorTuple); + auto paramPoint = halide2isl::makeIslAffFromExpr(paramSpace, args[i]); + if (!paramPoint.is_null()) { + auto domainPoint = paramPoint.unbind_params_insert_domain(tensorTuple); access = access.intersect(domainPoint.eq_set(rangePoint)); } } @@ -293,14 +305,15 @@ isl::map extractAccess( isl::id tagID(domain.paramSpace.get_ctx(), tag); accesses->emplace(op, tagID); auto domainSpace = map.get_space().domain(); - auto tagSpace = domainSpace.params().add_named_tuple_id_ui(tagID, 0); - domainSpace = domainSpace.product(tagSpace).unwrap(); - map = map.preimage_domain(isl::multi_aff::domain_map(domainSpace)); - - return map; + auto tagSpace = domainSpace.params().add_named_tuple_id_ui(tagID, 0); + auto taggedSpace = domainSpace.product(tagSpace).unwrap(); + return map.preimage_domain(domainMap(taggedSpace)); } -std::pair extractAccesses( +std::pair< + isl::UnionMap, Tensor>, + isl::UnionMap, Tensor>> +extractAccesses( const IterationDomain& domain, const Stmt& s, AccessMap* accesses) { @@ -325,7 +338,7 @@ std::pair extractAccesses( AccessMap* accesses; public: - isl::union_map reads, writes; + isl::UnionMap, Tensor> reads, writes; FindAccesses(const IterationDomain& domain, AccessMap* accesses) : domain(domain), @@ -355,24 +368,26 @@ bool isReductionUpdate(const Provide* op) { * then converted into an expression on that iteration domain * by reinterpreting the parameters as input dimensions. */ -static isl::multi_aff mapToOther( +template +static isl::MultiAff mapToOther( const IterationDomain& iterationDomain, std::unordered_set skip, isl::id id) { auto ctx = iterationDomain.tuple.get_ctx(); - auto list = isl::aff_list(ctx, 0); + auto list = isl::AffListOn(ctx, 0); for (auto id : iterationDomain.tuple.get_id_list()) { if (skip.count(id.get_name()) == 1) { continue; } - auto aff = isl::aff::param_on_domain_space(iterationDomain.paramSpace, id); - aff = aff.unbind_params_insert_domain(iterationDomain.tuple); - list = list.add(aff); + auto aff = + isl::AffOn<>::param_on_domain_space(iterationDomain.paramSpace, id); + list = list.add(aff.unbind_params_insert_domain(iterationDomain.tuple)); } auto domainSpace = iterationDomain.tuple.get_space(); - auto space = domainSpace.params().add_named_tuple_id_ui(id, list.size()); - space = domainSpace.product(space).unwrap(); - return isl::multi_aff(space, list); + auto space = + domainSpace.params().add_named_tuple_id_ui(id, list.size()); + auto productSpace = domainSpace.product(space).unwrap(); + return isl::MultiAff(productSpace, list); } /* @@ -417,7 +432,8 @@ isl::union_map extractReduction( } auto ctx = iterationDomain.tuple.get_ctx(); isl::id id(ctx, kReductionLabel + op->name + "_" + std::to_string(index)); - auto reduction = mapToOther(iterationDomain, finder.reductionVars, id); + auto reduction = + mapToOther(iterationDomain, finder.reductionVars, id); return isl::union_map(isl::map(reduction)); } @@ -458,7 +474,7 @@ onDomains(isl::aff f, isl::union_set domain, const IterationDomainMap& map) { */ isl::schedule makeScheduleTreeHelper( const Stmt& s, - isl::set set, + isl::Set<> set, isl::id_list outer, Body* body, AccessMap* accesses, @@ -472,7 +488,7 @@ isl::schedule makeScheduleTreeHelper( // Construct a variable (affine function) that references // the new parameter. - auto loopVar = isl::aff::param_on_domain_space(space, id); + auto loopVar = isl::AffOn<>::param_on_domain_space(space, id); // Then we add our new loop bound constraints. auto lbs = @@ -527,16 +543,16 @@ isl::schedule makeScheduleTreeHelper( size_t stmtIndex = statements->size(); isl::id id(set.get_ctx(), kStatementLabel + std::to_string(stmtIndex)); statements->emplace(id, op); - auto tupleSpace = isl::space(set.get_ctx(), 0); - tupleSpace = tupleSpace.add_named_tuple_id_ui(id, outer.size()); + auto space = isl::Space<>(set.get_ctx(), 0); + auto tupleSpace = space.add_named_tuple_id_ui(id, outer.size()); IterationDomain iterationDomain; iterationDomain.paramSpace = set.get_space(); - iterationDomain.tuple = isl::multi_id(tupleSpace, outer); + iterationDomain.tuple = isl::MultiId(tupleSpace, outer); domains->emplace(id, iterationDomain); auto domain = set.unbind_params(iterationDomain.tuple); schedule = isl::schedule::from_domain(domain); - isl::union_map newReads, newWrites; + isl::UnionMap, Tensor> newReads, newWrites; std::tie(newReads, newWrites) = extractAccesses(iterationDomain, op, accesses); // A tensor may be involved in multiple reductions. @@ -553,7 +569,9 @@ isl::schedule makeScheduleTreeHelper( return schedule; }; -ScheduleTreeAndAccesses makeScheduleTree(isl::space paramSpace, const Stmt& s) { +ScheduleTreeAndAccesses makeScheduleTree( + isl::Space<> paramSpace, + const Stmt& s) { ScheduleTreeAndAccesses result; Body body(paramSpace); @@ -562,7 +580,7 @@ ScheduleTreeAndAccesses makeScheduleTree(isl::space paramSpace, const Stmt& s) { isl::id_list outer(paramSpace.get_ctx(), 0); auto schedule = makeScheduleTreeHelper( s, - isl::set::universe(paramSpace), + isl::Set<>::universe(paramSpace), outer, &body, &result.accesses, diff --git a/tc/core/halide2isl.h b/tc/core/halide2isl.h index b3ecc95ce..f735846a1 100644 --- a/tc/core/halide2isl.h +++ b/tc/core/halide2isl.h @@ -23,6 +23,7 @@ #include #include "tc/core/polyhedral/body.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_tree.h" #include "tc/core/tc2halide.h" #include "tc/external/isl.h" @@ -43,14 +44,14 @@ struct SymbolTable { SymbolTable makeSymbolTable(const tc2halide::HalideComponents& components); /// Make the space of all given parameter values -isl::space makeParamSpace(isl::ctx ctx, const ParameterVector& params); +isl::Space<> makeParamSpace(isl::ctx ctx, const ParameterVector& params); /// Make the parameter set marking all given parameters /// as non-negative. -isl::set makeParamContext(isl::ctx ctx, const ParameterVector& params); +isl::Set<> makeParamContext(isl::ctx ctx, const ParameterVector& params); /// Make a constant-valued affine function over a space. -isl::aff makeIslAffFromInt(isl::space space, int64_t i); +isl::AffOn<> makeIslAffFromInt(isl::Space<> space, int64_t i); // Make an affine function over a space from a Halide Expr. Returns a // null isl::aff if the expression is not affine. Fails if Variable @@ -58,17 +59,17 @@ isl::aff makeIslAffFromInt(isl::space space, int64_t i); // Note that the input space can be either a parameter space or // a set space, but the expression can only reference // the parameters in the space. -isl::aff makeIslAffFromExpr(isl::space space, const Halide::Expr& e); +isl::AffOn<> makeIslAffFromExpr(isl::Space<> space, const Halide::Expr& e); // Iteration domain information associated to a statement identifier. struct IterationDomain { // All parameters active at the point where the iteration domain // was created, including those corresponding to outer loop iterators. - isl::space paramSpace; + isl::Space<> paramSpace; // The identifier tuple corresponding to the iteration domain. // The identifiers in the tuple are the outer loop iterators, // from outermost to innermost. - isl::multi_id tuple; + isl::MultiId tuple; }; typedef std::unordered_map @@ -102,7 +103,7 @@ struct ScheduleTreeAndAccesses { /// Make a schedule tree from a Halide Stmt, along with auxiliary data /// structures describing the memory access patterns. ScheduleTreeAndAccesses makeScheduleTree( - isl::space paramSpace, + isl::Space<> paramSpace, const Halide::Internal::Stmt& s); } // namespace halide2isl diff --git a/tc/core/polyhedral/domain_types.h b/tc/core/polyhedral/domain_types.h index 96b740bd2..433666c25 100644 --- a/tc/core/polyhedral/domain_types.h +++ b/tc/core/polyhedral/domain_types.h @@ -2,6 +2,9 @@ namespace tc { namespace polyhedral { struct Prefix; +struct Reduction; +struct Statement; +struct Tag; struct Tensor; } // namespace polyhedral From c67f613a8604f4d24ab0c68fac800541990a5240 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 22/85] halide2isl.cc: extractReduction: use templated isl types --- tc/core/halide2isl.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tc/core/halide2isl.cc b/tc/core/halide2isl.cc index 912231fae..fef70e0fe 100644 --- a/tc/core/halide2isl.cc +++ b/tc/core/halide2isl.cc @@ -407,7 +407,7 @@ static isl::MultiAff mapToOther( * that all statement instances that belong to the same reduction * write to the same tensor element. */ -isl::union_map extractReduction( +isl::UnionMap extractReduction( const IterationDomain& iterationDomain, const Provide* op, size_t index) { @@ -424,17 +424,19 @@ isl::union_map extractReduction( } finder; if (!isReductionUpdate(op)) { - return isl::union_map::empty(iterationDomain.tuple.get_space().params()); + auto space = iterationDomain.tuple.get_space().params(); + return isl::UnionMap::empty(space); } op->accept(&finder); if (finder.reductionVars.size() == 0) { - return isl::union_map::empty(iterationDomain.tuple.get_space().params()); + auto space = iterationDomain.tuple.get_space().params(); + return isl::UnionMap(isl::union_map::empty(space)); } auto ctx = iterationDomain.tuple.get_ctx(); isl::id id(ctx, kReductionLabel + op->name + "_" + std::to_string(index)); auto reduction = mapToOther(iterationDomain, finder.reductionVars, id); - return isl::union_map(isl::map(reduction)); + return reduction.asMap().asUnionMap(); } /* From d773ced6976ad3d54d01342f3ff7fb951363b04d Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 23/85] Scop::context: remove explicit cast Now that halide2isl::makeParamContext has been converted to templated isl types, the cast is no longer required. --- tc/core/polyhedral/scop.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/core/polyhedral/scop.h b/tc/core/polyhedral/scop.h index b59e8bb20..059ec38f5 100644 --- a/tc/core/polyhedral/scop.h +++ b/tc/core/polyhedral/scop.h @@ -97,7 +97,7 @@ struct Scop { isl::Set<> context() const { auto ctx = domain().get_ctx(); auto context = halide2isl::makeParamContext(ctx, halide.params); - return isl::Set<>(context.intersect(makeContext(parameterValues))); + return context.intersect(makeContext(parameterValues)); } // Specialize a Scop by fixing the given parameters to the given sizes. From 30c243006a285f0e72afea76ad0329da354e1092 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 24/85] Scop::domain(): use templated isl types This commit introduces a cast, which will be removed after schedule trees have been converted to templated isl types. --- tc/core/polyhedral/scop.cc | 5 +++-- tc/core/polyhedral/scop.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tc/core/polyhedral/scop.cc b/tc/core/polyhedral/scop.cc index 5edb94455..e7fbe191c 100644 --- a/tc/core/polyhedral/scop.cc +++ b/tc/core/polyhedral/scop.cc @@ -27,6 +27,7 @@ #include "tc/core/functional.h" #include "tc/core/halide2isl.h" #include "tc/core/polyhedral/body.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/memory_promotion.h" #include "tc/core/polyhedral/schedule_isl_conversion.h" #include "tc/core/polyhedral/schedule_transforms.h" @@ -97,8 +98,8 @@ isl::union_set& Scop::domainRef() { return dom->domain_; } -const isl::union_set Scop::domain() const { - return const_cast(this)->domainRef(); +const isl::UnionSet Scop::domain() const { + return isl::UnionSet(const_cast(this)->domainRef()); } std::ostream& operator<<(std::ostream& os, const Scop& s) { diff --git a/tc/core/polyhedral/scop.h b/tc/core/polyhedral/scop.h index 059ec38f5..c426a2c28 100644 --- a/tc/core/polyhedral/scop.h +++ b/tc/core/polyhedral/scop.h @@ -27,6 +27,7 @@ #include "tc/core/halide2isl.h" #include "tc/core/mapping_options.h" #include "tc/core/polyhedral/body.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_transforms.h" #include "tc/core/polyhedral/schedule_tree.h" #include "tc/core/tc2halide.h" @@ -510,7 +511,7 @@ struct Scop { isl::union_set& domainRef(); public: - const isl::union_set domain() const; + const isl::UnionSet domain() const; // The parameter values of a specialized Scop. std::unordered_map parameterValues; From 31f372920a0196fb2d32143366788aa2abe51d81 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 25/85] memory_promotion.cc: tensorElementsSet: remove explicit cast Now that Scop::Domain() has been converted to templated isl types, the cast is no longer required. --- tc/core/polyhedral/memory_promotion.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index 1cacd0e7b..e5741c5b4 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -410,7 +410,7 @@ namespace { // context of the scop. isl::set tensorElementsSet(const Scop& scop, isl::id tensorId) { auto halideParameter = scop.findArgument(tensorId).parameter(); - auto space = isl::Space<>(scop.domain().get_space()); + auto space = scop.domain().get_space(); auto nDim = halideParameter.dimensions(); auto tensorTuple = constructTensorTuple(space, tensorId, nDim); auto tensorSpace = tensorTuple.get_space(); From 82d1ecd2106a0623ad5f9806f5cddc94e47d0a01 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 26/85] Scop::makeContext: remove explicit cast Now that Scop::Domain() has been converted to templated isl types, the cast is no longer required. --- tc/core/polyhedral/scop.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/core/polyhedral/scop.h b/tc/core/polyhedral/scop.h index c426a2c28..6b2ebc06f 100644 --- a/tc/core/polyhedral/scop.h +++ b/tc/core/polyhedral/scop.h @@ -137,7 +137,7 @@ struct Scop { isl::Set<> makeContext( const std::unordered_map& sizes = std::unordered_map()) const { - auto s = isl::Space<>(domain().get_space()); + auto s = domain().get_space(); return makeSpecializationSet(s, sizes); } From 8d70dff78db98bc038188b225225c5e091848d98 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 27/85] makeParameterContext: use templated isl types Use explicit API calls instead of operators because the use of aff_set is confusing (at least to the author of this commit). The conversions to isl::PwAff are needed because, unlike the Python bindings, the C++ bindings do not have a class hierarchy. The conversions could also be avoided by introducing an isl_aff_nonneg_set and an isl_aff_pos_set in isl. --- tc/core/polyhedral/cuda/mapped_scop.cc | 3 ++- tc/external/detail/islpp.h | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index eb555d94f..2594a00e4 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -866,7 +866,8 @@ void MappedScop::insertMappingContext() { auto space = scop.domain().get_space(); auto mappingContext = makeParameterContext( space, mappingIdsWithSizes.begin(), mappingIdsWithSizes.end()); - updateTopLevelContext(scop.scheduleRoot(), mappingContext.from_params()); + updateTopLevelContext( + scop.scheduleRoot(), mappingContext.from_params()); } namespace { diff --git a/tc/external/detail/islpp.h b/tc/external/detail/islpp.h index 1d730d6b7..d527c4192 100644 --- a/tc/external/detail/islpp.h +++ b/tc/external/detail/islpp.h @@ -291,17 +291,17 @@ isl::multi_val makeMultiVal(isl::space s, const std::vector& vals) { // 2. each new parameter dimension p(i) is bounded to be in [0, e(i) - 1] // 3. if e (i) == 0 then no constraint is set on the corresponding id(i) template -inline isl::set makeParameterContext( - isl::space paramSpace, +inline isl::Set<> makeParameterContext( + isl::Space<> paramSpace, const IterPair begin, const IterPair end) { for (auto it = begin; it != end; ++it) { paramSpace = paramSpace.add_param(it->first); } - isl::set res(isl::set::universe(paramSpace)); + auto res(isl::Set<>::universe(paramSpace)); for (auto it = begin; it != end; ++it) { - isl::aff a(isl::aff::param_on_domain_space(paramSpace, it->first)); - res = res & (isl::aff_set(a) >= 0) & (isl::aff_set(a) < it->second); + auto a(isl::AffOn<>::param_on_domain_space(paramSpace, it->first)); + res = res & a.asPwAff().nonneg_set() & (it->second - a).asPwAff().pos_set(); } return res; } From 891aa8724c31154dfc81135df28aa96031651060 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 28/85] partialScheduleMupa: use templated isl types An explicit cast is introduced in partialScheduleMupa, which will be removed after the schedule tree has been converted to templated isl types. Automatic type deduction is temporarily turned off in promoteToSharedBelow to avoid having to convert the entire promoteToSharedBelow together with partialScheduleMupa. It will be reintroduced after the schedule tree has been converted to templated isl types. --- tc/core/polyhedral/cuda/memory_promotion_heuristic.cc | 6 ++++-- tc/core/polyhedral/schedule_utils-inl.h | 9 ++++++--- tc/core/polyhedral/schedule_utils.h | 4 +++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index 928ee904a..f44ab4251 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -19,6 +19,7 @@ #include "tc/core/polyhedral/cuda/mapped_scop.h" #include "tc/core/polyhedral/cuda/mapping_types.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/exceptions.h" #include "tc/core/polyhedral/memory_promotion.h" #include "tc/core/polyhedral/schedule_tree.h" @@ -477,7 +478,7 @@ void promoteToSharedBelow( auto groupMap = TensorReferenceGroup::accessedWithin( partialSched.intersect_domain(mapping), scop.body); // Pure affine schedule without (mapping) filters. - auto partialSchedMupa = partialScheduleMupa(root, node); + auto partialSchedMupa = partialScheduleMupa(root, node); // Prepare groups for sorting, to have specified order necessary for // reproducibility and tests. @@ -653,7 +654,8 @@ void promoteToRegistersBelow(MappedScop& mscop, detail::ScheduleTree* scope) { auto blockSchedule = mscop.blockMappingSchedule(mscop.schedule()); // Pure affine schedule without (mapping) filters. - auto partialSchedMupa = partialScheduleMupa(root, scope); + isl::multi_union_pw_aff partialSchedMupa = + partialScheduleMupa(root, scope); // Schedule with block mapping filter. auto partialSched = isl::union_map::from(partialSchedMupa).intersect_domain(blockMapping); diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index 3c6be4645..65aad9bbd 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -18,6 +18,7 @@ #include #include "tc/core/check.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_tree.h" #include "tc/core/polyhedral/schedule_tree_elem.h" #include "tc/external/isl.h" @@ -137,14 +138,16 @@ inline isl::multi_union_pw_aff prefixScheduleMupa( return infixScheduleMupa(root, root, tree); } -inline isl::multi_union_pw_aff partialScheduleMupa( +template +inline isl::MultiUnionPwAff partialScheduleMupa( const detail::ScheduleTree* root, const detail::ScheduleTree* tree) { using namespace polyhedral::detail; auto prefix = prefixScheduleMupa(root, tree); - auto band = tree->as(); - return band ? prefix.flat_range_product(band->mupa_) : prefix; + auto band = tree->as(); + auto partial = band ? prefix.flat_range_product(band->mupa_) : prefix; + return isl::MultiUnionPwAff(partial); } /* diff --git a/tc/core/polyhedral/schedule_utils.h b/tc/core/polyhedral/schedule_utils.h index 93bcff92d..5ced261b0 100644 --- a/tc/core/polyhedral/schedule_utils.h +++ b/tc/core/polyhedral/schedule_utils.h @@ -19,6 +19,7 @@ #include "tc/core/check.h" #include "tc/core/constants.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_tree.h" #include "tc/core/polyhedral/schedule_tree_elem.h" @@ -86,7 +87,8 @@ isl::multi_union_pw_aff prefixScheduleMupa( // including that of the node itself. // Note that this function does not take into account // any intermediate filter nodes. -isl::multi_union_pw_aff partialScheduleMupa( +template +isl::MultiUnionPwAff partialScheduleMupa( const detail::ScheduleTree* root, const detail::ScheduleTree* tree); From b59fac15c23947c8d81df7d421005bd3555df3dd Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 29/85] prefixScheduleMupa: use templated isl types An explicit cast is introduced in prefixScheduleMupa, which will be removed when infixScheduleMupa is converted to templated isl types. Automatic type deduction is temporarily turned off in MappedScop::detectReductions to avoid having to convert the entire MappedScop::detectReductions together with prefixScheduleMupa. It will be reintroduced which will be removed when memberRange is converted to templated isl types. Automatic type deduction is also temporarily turned off in partialScheduleMupa. It will be reintroduced after the schedule tree has been converted to templated isl types. --- tc/core/polyhedral/cuda/mapped_scop.cc | 4 ++-- tc/core/polyhedral/schedule_transforms.cc | 4 ++-- tc/core/polyhedral/schedule_utils-inl.h | 8 +++++--- tc/core/polyhedral/schedule_utils.h | 3 ++- tc/core/polyhedral/scop.cc | 4 ++-- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index 2594a00e4..dbe0538a7 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -296,7 +296,7 @@ bool MappedScop::detectReductions(ScheduleTree* tree) { }); // The outer (coincident) members, together with the prefix schedule, // need to determine a single reduction. - auto prefix = prefixScheduleMupa(schedule(), tree); + isl::multi_union_pw_aff prefix = prefixScheduleMupa(schedule(), tree); prefix = prefix.range_product(band->memberRange(0, nCoincident)); if (!isSingleReductionWithin(updates, prefix, scop())) { return false; @@ -342,7 +342,7 @@ ScheduleTree* MappedScop::separateReduction(ScheduleTree* st) { auto root = scop_->scheduleRoot(); auto domain = activeDomainPoints(root, st); - auto prefixSchedule = prefixScheduleMupa(root, st); + auto prefixSchedule = prefixScheduleMupa(root, st); auto reductionSchedule = reductionMapSchedule(st); auto space = reductionSchedule.get_space(); auto size = isl::multi_val::zero(space); diff --git a/tc/core/polyhedral/schedule_transforms.cc b/tc/core/polyhedral/schedule_transforms.cc index 2aee2e095..082235496 100644 --- a/tc/core/polyhedral/schedule_transforms.cc +++ b/tc/core/polyhedral/schedule_transforms.cc @@ -363,9 +363,9 @@ detail::ScheduleTree* insertEmptyExtensionAbove( * with the given identifier. */ isl::map labelExtension(ScheduleTree* root, ScheduleTree* tree, isl::id id) { - auto prefix = prefixScheduleMupa(root, tree); + auto prefix = prefixScheduleMupa(root, tree); auto scheduleSpace = prefix.get_space(); - auto space = scheduleSpace.params().add_named_tuple_id_ui(id, 0); + auto space = scheduleSpace.params().add_named_tuple_id_ui(id, 0); auto extensionSpace = scheduleSpace.map_from_domain_and_range(space); return isl::map::universe(extensionSpace); } diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index 65aad9bbd..6f868c70c 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -132,10 +132,12 @@ inline isl::multi_union_pw_aff infixScheduleMupa( return prefix; } -inline isl::multi_union_pw_aff prefixScheduleMupa( +template +inline isl::MultiUnionPwAff prefixScheduleMupa( const detail::ScheduleTree* root, const detail::ScheduleTree* tree) { - return infixScheduleMupa(root, root, tree); + auto prefix = infixScheduleMupa(root, root, tree); + return isl::MultiUnionPwAff(prefix); } template @@ -144,7 +146,7 @@ inline isl::MultiUnionPwAff partialScheduleMupa( const detail::ScheduleTree* tree) { using namespace polyhedral::detail; - auto prefix = prefixScheduleMupa(root, tree); + isl::multi_union_pw_aff prefix = prefixScheduleMupa(root, tree); auto band = tree->as(); auto partial = band ? prefix.flat_range_product(band->mupa_) : prefix; return isl::MultiUnionPwAff(partial); diff --git a/tc/core/polyhedral/schedule_utils.h b/tc/core/polyhedral/schedule_utils.h index 5ced261b0..36e77fd40 100644 --- a/tc/core/polyhedral/schedule_utils.h +++ b/tc/core/polyhedral/schedule_utils.h @@ -79,7 +79,8 @@ isl::multi_union_pw_aff infixScheduleMupa( // function on the universe domain of the schedule tree. // Note that unlike isl_schedule_node_get_prefix_schedule_multi_union_pw_aff, // this function does not take into account any intermediate filter nodes. -isl::multi_union_pw_aff prefixScheduleMupa( +template +isl::MultiUnionPwAff prefixScheduleMupa( const detail::ScheduleTree* root, const detail::ScheduleTree* tree); diff --git a/tc/core/polyhedral/scop.cc b/tc/core/polyhedral/scop.cc index e7fbe191c..791cb138e 100644 --- a/tc/core/polyhedral/scop.cc +++ b/tc/core/polyhedral/scop.cc @@ -370,7 +370,7 @@ void Scop::computeAllDependences() { } isl::union_map Scop::activeDependences(detail::ScheduleTree* tree) { - auto prefix = prefixScheduleMupa(scheduleRoot(), tree); + auto prefix = prefixScheduleMupa(scheduleRoot(), tree); auto domain = activeDomainPoints(scheduleRoot(), tree); auto active = dependences; active = active.intersect_domain(domain); @@ -485,7 +485,7 @@ void Scop::reschedule( auto parentTree = tree->ancestor(root, 1); auto treePos = tree->positionInParent(parentTree); auto domain = activeDomainPoints(root, tree); - auto prefix = prefixScheduleMupa(root, tree); + auto prefix = prefixScheduleMupa(root, tree); // Restrict the constraints to domain points reachable from point loops // and update the current prefix. From 857fffcc9a25ca581023701c0a36b089ea8c10f8 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 30/85] memberRange: use templated isl types An explicit cast is introduced in memberRange, which will be removed when schedule trees are converted to templated isl types. --- tc/core/polyhedral/cuda/mapped_scop.cc | 6 +++--- tc/core/polyhedral/domain_types.h | 2 ++ tc/core/polyhedral/schedule_tree_elem.h | 8 ++++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index dbe0538a7..a406c195a 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -296,8 +296,8 @@ bool MappedScop::detectReductions(ScheduleTree* tree) { }); // The outer (coincident) members, together with the prefix schedule, // need to determine a single reduction. - isl::multi_union_pw_aff prefix = prefixScheduleMupa(schedule(), tree); - prefix = prefix.range_product(band->memberRange(0, nCoincident)); + auto prefix = prefixScheduleMupa(schedule(), tree) + .range_product(band->memberRange(0, nCoincident)); if (!isSingleReductionWithin(updates, prefix, scop())) { return false; } @@ -331,7 +331,7 @@ isl::multi_union_pw_aff MappedScop::reductionMapSchedule( TC_CHECK_GE(nMember, reductionDim + 1); auto first = reductionDim + 1 - nMappedThreads; - return reductionBand->memberRange(first, nMappedThreads); + return reductionBand->memberRange(first, nMappedThreads); } ScheduleTree* MappedScop::separateReduction(ScheduleTree* st) { diff --git a/tc/core/polyhedral/domain_types.h b/tc/core/polyhedral/domain_types.h index 433666c25..9fba84e32 100644 --- a/tc/core/polyhedral/domain_types.h +++ b/tc/core/polyhedral/domain_types.h @@ -1,8 +1,10 @@ namespace tc { namespace polyhedral { +struct Band; struct Prefix; struct Reduction; +struct ReductionSchedule; struct Statement; struct Tag; struct Tensor; diff --git a/tc/core/polyhedral/schedule_tree_elem.h b/tc/core/polyhedral/schedule_tree_elem.h index 91cc61444..a912fab5c 100644 --- a/tc/core/polyhedral/schedule_tree_elem.h +++ b/tc/core/polyhedral/schedule_tree_elem.h @@ -23,6 +23,7 @@ #include "tc/external/isl.h" #include "tc/core/check.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/mapping_types.h" #include "tc/core/polyhedral/schedule_tree.h" @@ -331,14 +332,17 @@ struct ScheduleTreeBand : public ScheduleTree { // Extract the range of "n" members starting at "first" // (in an anonymous space). - isl::multi_union_pw_aff memberRange(size_t first, size_t n) const { + template + isl::MultiUnionPwAff memberRange(size_t first, size_t n) + const { auto list = mupa_.get_union_pw_aff_list(); auto space = mupa_.get_space().params().add_unnamed_tuple_ui(n); auto end = first + n; TC_CHECK_LE(end, nMember()); list = list.drop(end, nMember() - end); list = list.drop(0, first); - return isl::multi_union_pw_aff(space, list); + return isl::MultiUnionPwAff( + isl::multi_union_pw_aff(space, list)); } public: From 47ec4482ac9bea137acf8892bb3a8bcbb5736eb0 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 31/85] reductionUpdates: use templated isl types An explicit cast is introduced in reductionUpdates, which will be removed when Body is converted to templated isl types. --- tc/core/polyhedral/reduction_matcher.cc | 7 +++++-- tc/core/polyhedral/schedule_tree_matcher.h | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tc/core/polyhedral/reduction_matcher.cc b/tc/core/polyhedral/reduction_matcher.cc index 59aeaf13f..64efc852b 100644 --- a/tc/core/polyhedral/reduction_matcher.cc +++ b/tc/core/polyhedral/reduction_matcher.cc @@ -18,6 +18,7 @@ #include #include "tc/core/check.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_tree.h" #include "tc/core/polyhedral/scop.h" #include "tc/external/isl.h" @@ -54,7 +55,9 @@ bool isSupportedReductionUpdateId(isl::id id, const Scop& scop) { } // namespace -isl::union_set reductionUpdates(isl::union_set domain, const Scop& scop) { +isl::UnionSet reductionUpdates( + isl::union_set domain, + const Scop& scop) { domain = scop.body.reductions.intersect_domain(domain).domain(); auto update = isl::union_set::empty(domain.get_space()); domain.foreach_set([&update, &scop](isl::set set) { @@ -63,7 +66,7 @@ isl::union_set reductionUpdates(isl::union_set domain, const Scop& scop) { update = update.unite(set); } }); - return update; + return isl::UnionSet(update); } } // namespace polyhedral diff --git a/tc/core/polyhedral/schedule_tree_matcher.h b/tc/core/polyhedral/schedule_tree_matcher.h index fd4b986a9..173cfee95 100644 --- a/tc/core/polyhedral/schedule_tree_matcher.h +++ b/tc/core/polyhedral/schedule_tree_matcher.h @@ -19,6 +19,7 @@ #include #include +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_tree.h" #include "tc/core/polyhedral/scop.h" @@ -27,7 +28,9 @@ namespace polyhedral { // Return the union of the reduction update statements // that appear in "domain". -isl::union_set reductionUpdates(isl::union_set domain, const Scop& scop); +isl::UnionSet reductionUpdates( + isl::union_set domain, + const Scop& scop); // Does "prefix" partition "domain" into individual reductions? // In particular, do the elements of "domain" access a single tensor From 2b654288251968d17ef0e628cda695844b6e4cf3 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 32/85] isSingleReductionWithin: use templated isl types An explicit cast is introduced in MappedScop::detectReductions, which will be removed after the schedule tree has been converted to templated isl types. --- tc/core/polyhedral/cuda/mapped_scop.cc | 2 +- tc/core/polyhedral/schedule_tree_matcher-inl.h | 8 +++++--- tc/core/polyhedral/schedule_tree_matcher.h | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index a406c195a..f503c84ad 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -285,7 +285,7 @@ bool MappedScop::detectReductions(ScheduleTree* tree) { // a single reduction for now. // Support for multiple reductions would require a check // that these reductions do not interfere with each other. - auto domain = band->mupa_.domain(); + auto domain = isl::UnionSet(band->mupa_.domain()); auto updates = reductionUpdates(domain, scop()); if (updates.n_set() != 1) { return false; diff --git a/tc/core/polyhedral/schedule_tree_matcher-inl.h b/tc/core/polyhedral/schedule_tree_matcher-inl.h index 8a2b2196c..1a83746cd 100644 --- a/tc/core/polyhedral/schedule_tree_matcher-inl.h +++ b/tc/core/polyhedral/schedule_tree_matcher-inl.h @@ -16,6 +16,7 @@ #pragma once #include "tc/core/check.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_tree.h" #include "tc/core/polyhedral/schedule_tree_elem.h" @@ -291,13 +292,14 @@ inline std::vector match( return matchDFSPreorder(matcher, tree); } +template inline bool isSingleReductionWithin( - isl::union_set domain, - isl::multi_union_pw_aff prefix, + isl::UnionSet domain, + isl::MultiUnionPwAff prefix, const Scop& scop) { auto reductions = scop.body.reductions; reductions = reductions.intersect_domain(domain); - auto prefixMap = isl::union_map::from(prefix); + auto prefixMap = prefix.toUnionMap(); auto prefixToReduction = reductions.apply_domain(prefixMap); return prefixToReduction.is_single_valued(); } diff --git a/tc/core/polyhedral/schedule_tree_matcher.h b/tc/core/polyhedral/schedule_tree_matcher.h index 173cfee95..9827c0b80 100644 --- a/tc/core/polyhedral/schedule_tree_matcher.h +++ b/tc/core/polyhedral/schedule_tree_matcher.h @@ -35,9 +35,10 @@ isl::UnionSet reductionUpdates( // Does "prefix" partition "domain" into individual reductions? // In particular, do the elements of "domain" access a single tensor // element within "prefix"? +template bool isSingleReductionWithin( - isl::union_set domain, - isl::multi_union_pw_aff prefix, + isl::UnionSet domain, + isl::MultiUnionPwAff prefix, const Scop& scop); } // namespace polyhedral From 35782ae3c539f9c21a0bcba328a242bdc30b4ebe Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 33/85] Body: use templated isl types --- tc/core/polyhedral/body.h | 11 +++++++---- tc/core/polyhedral/reduction_matcher.cc | 8 ++++---- tc/core/polyhedral/schedule_tree_matcher.h | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/tc/core/polyhedral/body.h b/tc/core/polyhedral/body.h index 7461a5cc9..7186cacdd 100644 --- a/tc/core/polyhedral/body.h +++ b/tc/core/polyhedral/body.h @@ -17,6 +17,7 @@ #include +#include "tc/core/polyhedral/domain_types.h" #include "tc/external/isl.h" namespace tc { @@ -26,11 +27,13 @@ namespace polyhedral { struct Body { Body() = default; Body(isl::space paramSpace) { - reductions = writes = reads = isl::union_map::empty(paramSpace); + auto empty = isl::union_map::empty(paramSpace); + writes = reads = isl::UnionMap, Tensor>(empty); + reductions = isl::UnionMap(empty); } // Specialize to the given context. - void specialize(isl::set context) { + void specialize(isl::Set<> context) { reads = reads.intersect_params(context); writes = writes.intersect_params(context); reductions = reductions.intersect_params(context); @@ -39,7 +42,7 @@ struct Body { // Union maps describing the reads and writes done. Uses the ids in // the schedule tree to denote the containing Stmt, and tags each // access with a unique reference id of the form __tc_ref_N. - isl::union_map reads, writes; + isl::UnionMap, Tensor> reads, writes; // A function on reduction update statement instances that partitions them // into individual reductions, where each reduction consists of @@ -73,7 +76,7 @@ struct Body { // That is, in the example above, it would just be // // { S[i] -> R[] : 0 <= i < 4 } - isl::union_map reductions; + isl::UnionMap reductions; }; std::ostream& operator<<(std::ostream& os, const Body& body); diff --git a/tc/core/polyhedral/reduction_matcher.cc b/tc/core/polyhedral/reduction_matcher.cc index 64efc852b..318e9bd6f 100644 --- a/tc/core/polyhedral/reduction_matcher.cc +++ b/tc/core/polyhedral/reduction_matcher.cc @@ -56,17 +56,17 @@ bool isSupportedReductionUpdateId(isl::id id, const Scop& scop) { } // namespace isl::UnionSet reductionUpdates( - isl::union_set domain, + isl::UnionSet domain, const Scop& scop) { domain = scop.body.reductions.intersect_domain(domain).domain(); - auto update = isl::union_set::empty(domain.get_space()); - domain.foreach_set([&update, &scop](isl::set set) { + auto update = isl::UnionSet::empty(domain.get_space()); + domain.foreach_set([&update, &scop](isl::Set set) { auto setId = set.get_tuple_id(); if (isSupportedReductionUpdateId(setId, scop)) { update = update.unite(set); } }); - return isl::UnionSet(update); + return update; } } // namespace polyhedral diff --git a/tc/core/polyhedral/schedule_tree_matcher.h b/tc/core/polyhedral/schedule_tree_matcher.h index 9827c0b80..8b51f9ce9 100644 --- a/tc/core/polyhedral/schedule_tree_matcher.h +++ b/tc/core/polyhedral/schedule_tree_matcher.h @@ -29,7 +29,7 @@ namespace polyhedral { // Return the union of the reduction update statements // that appear in "domain". isl::UnionSet reductionUpdates( - isl::union_set domain, + isl::UnionSet domain, const Scop& scop); // Does "prefix" partition "domain" into individual reductions? From ff79e4397c0962083600d78ab1bce9e9cdbea967 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 34/85] reductionMapSchedule: use templated isl types --- tc/core/polyhedral/cuda/mapped_scop.cc | 6 +++--- tc/core/polyhedral/cuda/mapped_scop.h | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index f503c84ad..6ce5993b2 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -319,8 +319,8 @@ bool MappedScop::needReductionSeparation(const ScheduleTree* st) { return !reductionBandUpdates_.at(st).separated; } -isl::multi_union_pw_aff MappedScop::reductionMapSchedule( - const ScheduleTree* st) { +isl::MultiUnionPwAff +MappedScop::reductionMapSchedule(const ScheduleTree* st) { TC_CHECK(reductionBandUpdates_.count(st) == 1); auto reductionBand = st->as(); TC_CHECK(reductionBand); @@ -345,7 +345,7 @@ ScheduleTree* MappedScop::separateReduction(ScheduleTree* st) { auto prefixSchedule = prefixScheduleMupa(root, st); auto reductionSchedule = reductionMapSchedule(st); auto space = reductionSchedule.get_space(); - auto size = isl::multi_val::zero(space); + auto size = isl::MultiVal::zero(space); for (size_t i = 0; i < numThreads.view.size(); ++i) { auto pos = numThreads.view.size() - 1 - i; size = size.set_val(pos, isl::val(st->ctx_, numThreads.view[i])); diff --git a/tc/core/polyhedral/cuda/mapped_scop.h b/tc/core/polyhedral/cuda/mapped_scop.h index 47aef39c6..37c5426e0 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.h +++ b/tc/core/polyhedral/cuda/mapped_scop.h @@ -24,6 +24,7 @@ #include "tc/core/cuda/cuda_mapping_options.h" #include "tc/core/polyhedral/cuda/mapping_types.h" #include "tc/core/polyhedral/cuda/memory_promotion_heuristic.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/scop.h" #include "tc/core/tensor.h" #include "tc/external/isl.h" @@ -171,7 +172,8 @@ class MappedScop { // Return the schedule that will be used by mapInnermostBandsToThreads // for mapping to thread identifiers, with the last function // corresponding to thread identifier x. - isl::multi_union_pw_aff reductionMapSchedule(const detail::ScheduleTree* st); + isl::MultiUnionPwAff reductionMapSchedule( + const detail::ScheduleTree* st); // Separate out reductions that can be mapped to an entire block. // The remaining parts, if any, are no longer considered for replacement // by a library call. From 67cf92924612088e36270727aea55eac1423678d Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 35/85] separatedOut: use templated isl types --- tc/core/polyhedral/cuda/mapped_scop.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index 6ce5993b2..bdafd9900 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -226,7 +226,10 @@ void fixThreadsBelow(MappedScop& mscop, ScheduleTree* tree, size_t begin) { * Anything that depends on an update statement is ordered after * the update statements. Anything else is ordered before. */ -bool separatedOut(Scop& scop, ScheduleTree* tree, isl::union_set updates) { +bool separatedOut( + Scop& scop, + ScheduleTree* tree, + isl::UnionSet updates) { auto domain = activeDomainPoints(scop.scheduleRoot(), tree); auto other = domain.subtract(updates); if (other.is_empty()) { From fab14bb37f6772d7e0595bb9d32881428dbc631f Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 36/85] constructThreadToWarp: use templated isl types --- tc/core/polyhedral/cuda/mapped_scop.cc | 15 ++++++++------- tc/core/polyhedral/domain_types.h | 2 ++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index bdafd9900..35523d0db 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -505,18 +505,19 @@ constexpr auto kWarp = "warp"; * (of size "warpSize") to a warp identifier, * based on the thread sizes s_x, s_y up to s_z in "block". */ -isl::multi_aff constructThreadToWarp( +isl::MultiAff constructThreadToWarp( isl::ctx ctx, const unsigned warpSize, const Block& block) { - auto space = isl::space(ctx, 0); + auto space = isl::Space<>(ctx, 0); auto id = isl::id(ctx, kBlock); - auto blockSpace = space.add_named_tuple_id_ui(id, block.view.size()); - auto warpSpace = space.add_named_tuple_id_ui(isl::id(ctx, kWarp), 1); - auto aff = isl::aff::zero_on_domain(blockSpace); + auto blockSpace = space.add_named_tuple_id_ui(id, block.view.size()); + auto warpSpace = space.add_named_tuple_id_ui(isl::id(ctx, kWarp), 1); + auto aff = isl::AffOn::zero_on_domain(blockSpace); auto nThread = block.view.size(); - auto identity = isl::multi_aff::identity(blockSpace.map_from_set()); + auto identity = + isl::MultiAff::identity(blockSpace.map_from_set()); for (int i = nThread - 1; i >= 0; --i) { aff = aff.scale(isl::val(ctx, block.view[i])); aff = aff.add(identity.get_aff(i)); @@ -524,7 +525,7 @@ isl::multi_aff constructThreadToWarp( aff = aff.scale_down(isl::val(ctx, warpSize)).floor(); auto mapSpace = blockSpace.product(warpSpace).unwrap(); - return isl::multi_aff(mapSpace, isl::aff_list(aff)); + return isl::MultiAff(mapSpace, aff.asAffList()); } } // namespace diff --git a/tc/core/polyhedral/domain_types.h b/tc/core/polyhedral/domain_types.h index 9fba84e32..b627e53eb 100644 --- a/tc/core/polyhedral/domain_types.h +++ b/tc/core/polyhedral/domain_types.h @@ -8,6 +8,8 @@ struct ReductionSchedule; struct Statement; struct Tag; struct Tensor; +struct Thread; +struct Warp; } // namespace polyhedral } // namespace tc From 6d832c36e7f951024dd7a64a349f592e4981cae9 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 37/85] prefixSchedule: use templated isl types An explicit cast is introduced in prefixSchedule, which will be removed after the schedule tree has been converted to templated isl types. Automatic type deduction is temporarily turned off in collectDomain and unroll to avoid having to convert these entire functions together with prefixSchedule. It will be reintroduced when the schedule tree is converted to templated isl types. --- tc/core/polyhedral/cuda/memory_promotion_heuristic.cc | 2 +- tc/core/polyhedral/schedule_utils-inl.h | 6 ++++-- tc/core/polyhedral/schedule_utils.cc | 2 +- tc/core/polyhedral/schedule_utils.h | 3 ++- tc/core/polyhedral/unroll.cc | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index f44ab4251..3dc7dbf2b 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -226,7 +226,7 @@ bool promotionImprovesCoalescing( auto depth = marker->scheduleDepth(root); auto activePoints = activeDomainPoints(root, mapping); auto localAccesses = originalAccesses.intersect_domain(activePoints); - auto schedule = prefixSchedule(root, marker); + auto schedule = prefixSchedule(root, marker); auto scheduledAccesses = localAccesses.apply_domain(schedule); for (auto access : scheduledAccesses.get_map_list()) { auto scheduleSpace = access.get_space().domain(); diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index 6f868c70c..4e9d5e026 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -73,10 +73,12 @@ inline isl::union_map partialScheduleImpl( } } // namespace detail -inline isl::union_map prefixSchedule( +template +inline isl::UnionMap prefixSchedule( const detail::ScheduleTree* root, const detail::ScheduleTree* node) { - return detail::partialScheduleImpl(root, node, false); + auto prefix = detail::partialScheduleImpl(root, node, false); + return isl::UnionMap(prefix); } inline isl::union_map partialSchedule( diff --git a/tc/core/polyhedral/schedule_utils.cc b/tc/core/polyhedral/schedule_utils.cc index 1b5da0dfe..6ff67fa95 100644 --- a/tc/core/polyhedral/schedule_utils.cc +++ b/tc/core/polyhedral/schedule_utils.cc @@ -67,7 +67,7 @@ isl::union_set collectDomain( for (auto anc : nodes) { domain = filter(domain, anc); if (auto extensionElem = anc->as()) { - auto parentSchedule = prefixSchedule(root, anc); + isl::union_map parentSchedule = prefixSchedule(root, anc); auto extension = extensionElem->extension_; TC_CHECK(parentSchedule) << "missing root domain node"; parentSchedule = parentSchedule.intersect_domain(domain); diff --git a/tc/core/polyhedral/schedule_utils.h b/tc/core/polyhedral/schedule_utils.h index 36e77fd40..a734e66a6 100644 --- a/tc/core/polyhedral/schedule_utils.h +++ b/tc/core/polyhedral/schedule_utils.h @@ -58,7 +58,8 @@ isl::union_map partialSchedule( const detail::ScheduleTree* node); // Return the schedule defined by the ancestors of the given node. -isl::union_map prefixSchedule( +template +isl::UnionMap prefixSchedule( const detail::ScheduleTree* root, const detail::ScheduleTree* node); diff --git a/tc/core/polyhedral/unroll.cc b/tc/core/polyhedral/unroll.cc index e90e78f16..916253c27 100644 --- a/tc/core/polyhedral/unroll.cc +++ b/tc/core/polyhedral/unroll.cc @@ -184,7 +184,7 @@ void markUnroll( } auto unrollVal = isl::val(st->ctx_, unroll); - auto prefix = prefixSchedule(root, st); + isl::union_map prefix = prefixSchedule(root, st); prefix = prefix.intersect_domain(prefixMappingFilter(root, st)); boundInstancesAndMarkUnroll(st, prefix, unrollVal); } From 867a1f3deb58a03528345b6140d1bbcbf6820697 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 38/85] labelExtension: use templated isl types --- tc/core/polyhedral/schedule_transforms.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tc/core/polyhedral/schedule_transforms.cc b/tc/core/polyhedral/schedule_transforms.cc index 082235496..4f2700b15 100644 --- a/tc/core/polyhedral/schedule_transforms.cc +++ b/tc/core/polyhedral/schedule_transforms.cc @@ -362,12 +362,13 @@ detail::ScheduleTree* insertEmptyExtensionAbove( * Construct an extension map for a zero-dimensional statement * with the given identifier. */ -isl::map labelExtension(ScheduleTree* root, ScheduleTree* tree, isl::id id) { +isl::Map +labelExtension(ScheduleTree* root, ScheduleTree* tree, isl::id id) { auto prefix = prefixScheduleMupa(root, tree); auto scheduleSpace = prefix.get_space(); auto space = scheduleSpace.params().add_named_tuple_id_ui(id, 0); auto extensionSpace = scheduleSpace.map_from_domain_and_range(space); - return isl::map::universe(extensionSpace); + return isl::Map::universe(extensionSpace); } /* From cf3c49c84d56869d8576b9975cd08769f9a93242 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 39/85] labelFilterFromExtension: use templated isl types --- tc/core/polyhedral/schedule_transforms.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tc/core/polyhedral/schedule_transforms.cc b/tc/core/polyhedral/schedule_transforms.cc index 4f2700b15..bd054cfd2 100644 --- a/tc/core/polyhedral/schedule_transforms.cc +++ b/tc/core/polyhedral/schedule_transforms.cc @@ -375,7 +375,8 @@ labelExtension(ScheduleTree* root, ScheduleTree* tree, isl::id id) { * Construct a filter node for a zero-dimensional extension statement * with the given extension map. */ -ScheduleTreeUPtr labelFilterFromExtension(isl::map extension) { +ScheduleTreeUPtr labelFilterFromExtension( + isl::Map extension) { return detail::ScheduleTree::makeFilter(extension.range()); } From 9f96ce2f1b69c06b70a4b293a2ae1e4e6ab125b4 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 40/85] findCorePositions: use templated isl types --- tc/core/polyhedral/schedule_isl_conversion.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tc/core/polyhedral/schedule_isl_conversion.cc b/tc/core/polyhedral/schedule_isl_conversion.cc index 2b01979b9..505dc6acc 100644 --- a/tc/core/polyhedral/schedule_isl_conversion.cc +++ b/tc/core/polyhedral/schedule_isl_conversion.cc @@ -23,6 +23,7 @@ #include "tc/core/check.h" #include "tc/core/flags.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_transforms.h" #include "tc/external/isl.h" @@ -81,7 +82,7 @@ isl::schedule_node insertBranch( */ std::vector findCorePositions( const ScheduleTree* st, - isl::union_set domain) { + isl::UnionSet domain) { std::vector positions; TC_CHECK(st->as()); for (size_t i = 0; i < st->numChildren(); ++i) { @@ -125,7 +126,7 @@ isl::schedule_node insertExtension( isl::schedule_node node, const ScheduleTree* st) { auto depth0 = node.get_tree_depth(); - auto domain = node.get_universe_domain(); + auto domain = isl::UnionSet(node.get_universe_domain()); auto child = st->child({0}); auto corePos = findCorePositions(child, domain); TC_CHECK(!corePos.empty()); From bc4fb5a84ce085b0bde81483e2980fb9aaf3c834 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 41/85] partialSchedule: use templated isl types An explicit cast is introduced in partialSchedule, which will be removed after the schedule tree has been converted to templated isl types. Automatic type deduction is temporarily turned off in promoteToSharedBelow and promoteToRegistersBelow to avoid having to convert these entire functions together with partialSchedule. It will be reintroduced when collectMappingsTo is converted to templated isl types. --- tc/core/polyhedral/cuda/memory_promotion_heuristic.cc | 4 ++-- tc/core/polyhedral/schedule_utils-inl.h | 6 ++++-- tc/core/polyhedral/schedule_utils.h | 3 ++- tc/core/polyhedral/scop.cc | 2 +- test/test_cuda_mapper_memory_promotion.cc | 6 +++--- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index 3dc7dbf2b..5a9ba792f 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -472,7 +472,7 @@ void promoteToSharedBelow( throw promotion::IncorrectScope("cannot promote below a sequence/set node"); } - auto partialSched = partialSchedule(root, node); + isl::union_map partialSched = partialSchedule(root, node); auto mapping = collectMappingsTo(scop); auto groupMap = TensorReferenceGroup::accessedWithin( @@ -646,7 +646,7 @@ void promoteToRegistersBelow(MappedScop& mscop, detail::ScheduleTree* scope) { auto blockMapping = collectMappingsTo(scop); auto mapping = collectMappingsTo(scop).intersect(blockMapping); - auto schedule = partialSchedule(scop.scheduleRoot(), scope); + isl::union_map schedule = partialSchedule(scop.scheduleRoot(), scope); auto groupMap = TensorReferenceGroup::accessedWithin( schedule.intersect_domain(mapping), scop.body); diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index 4e9d5e026..bacb9ccc4 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -81,10 +81,12 @@ inline isl::UnionMap prefixSchedule( return isl::UnionMap(prefix); } -inline isl::union_map partialSchedule( +template +inline isl::UnionMap partialSchedule( const detail::ScheduleTree* root, const detail::ScheduleTree* node) { - return detail::partialScheduleImpl(root, node, true); + auto prefix = detail::partialScheduleImpl(root, node, true); + return isl::UnionMap(prefix); } namespace detail { diff --git a/tc/core/polyhedral/schedule_utils.h b/tc/core/polyhedral/schedule_utils.h index a734e66a6..989df9da2 100644 --- a/tc/core/polyhedral/schedule_utils.h +++ b/tc/core/polyhedral/schedule_utils.h @@ -53,7 +53,8 @@ isl::union_map extendSchedule( // Get the partial schedule defined by ancestors of the given node and the node // itself. -isl::union_map partialSchedule( +template +isl::UnionMap partialSchedule( const detail::ScheduleTree* root, const detail::ScheduleTree* node); diff --git a/tc/core/polyhedral/scop.cc b/tc/core/polyhedral/scop.cc index 791cb138e..5490a32cb 100644 --- a/tc/core/polyhedral/scop.cc +++ b/tc/core/polyhedral/scop.cc @@ -265,7 +265,7 @@ void Scop::promoteEverythingAt(std::vector pos) { auto tree = scheduleRoot()->child(pos); checkFiltersDisjointStatements(scheduleRoot()); - auto schedule = partialSchedule(root, tree); + auto schedule = partialSchedule(root, tree); auto groupMap = TensorReferenceGroup::accessedWithin(schedule, body); for (auto& p : groupMap) { diff --git a/test/test_cuda_mapper_memory_promotion.cc b/test/test_cuda_mapper_memory_promotion.cc index 0fb7405b8..8cf0bc05f 100644 --- a/test/test_cuda_mapper_memory_promotion.cc +++ b/test/test_cuda_mapper_memory_promotion.cc @@ -64,7 +64,7 @@ class TestMapper : public ::testing::Test { TensorGroups accessedBySubtree( const polyhedral::detail::ScheduleTree* tree, const Scop& scop) { - auto schedule = partialSchedule(scop.scheduleRoot(), tree); + auto schedule = partialSchedule(scop.scheduleRoot(), tree); return TensorReferenceGroup::accessedWithin(schedule, scop.body); } }; @@ -309,7 +309,7 @@ def fun(float(N, M) A, float(N, M) B) -> (C) { EXPECT_EQ( np, std::min(tile1, problemSize1) * std::min(tile2, problemSize2)); - auto schedule = partialSchedule( + auto schedule = partialSchedule( scop.scheduleRoot(), scop.scheduleRoot()->child(childPos)); auto scopedAccess = oneGroup->originalAccesses().apply_domain(schedule); TC_CHECK(scopedAccess.is_equal(oneGroup->scopedAccesses())) @@ -376,7 +376,7 @@ def fun(float(N, M) A) -> (B, C) { auto active = activeDomainPoints(scop.scheduleRoot(), t); LOG(INFO) << "Active: " << active; - auto schedule = partialSchedule(scop.scheduleRoot(), t); + auto schedule = partialSchedule(scop.scheduleRoot(), t); auto scopedAccess = groupsB[0]->originalAccesses().apply_domain(schedule); TC_CHECK(scopedAccess.is_equal(groupsB[0]->scopedAccesses())) << "expected original accesses " << groupsB[0]->originalAccesses() From 49bd2e1c8c6130435961ed99045f47dc025a61d5 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 1 Aug 2018 17:05:38 +0200 Subject: [PATCH 42/85] ScheduleTree::makeMappingUnsafe: explicitly cast mapping This will make it easier to gradually introduce the use of templated isl types by breaking a cycle. The explicit cast will be removed again when makeMapping is converted to templated isl types. --- tc/core/polyhedral/schedule_tree.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tc/core/polyhedral/schedule_tree.cc b/tc/core/polyhedral/schedule_tree.cc index c17c2542a..1c7779d8f 100644 --- a/tc/core/polyhedral/schedule_tree.cc +++ b/tc/core/polyhedral/schedule_tree.cc @@ -30,6 +30,7 @@ #include "tc/core/check.h" #include "tc/core/constants.h" #include "tc/core/functional.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_tree_elem.h" #include "tc/core/scope_guard.h" #include "tc/external/isl.h" @@ -243,7 +244,8 @@ std::unique_ptr ScheduleTree::makeMappingUnsafe( << "expected as many mapped ids as affs"; ScheduleTreeMapping::Mapping mapping; for (size_t i = 0, n = mappedAffs.size(); i < n; ++i) { - mapping.emplace(mappedIds.at(i), mappedAffs.get_at(i)); + auto aff = isl::UnionPwAffOn(mappedAffs.get_at(i)); + mapping.emplace(mappedIds.at(i), aff); } TC_CHECK_GE(mapping.size(), 1u) << "empty mapping"; TC_CHECK_EQ(mappedIds.size(), mapping.size()) From 56d21fb595252ab156d54f5d944e85601072baab Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 43/85] ScheduleTreeMapping::Mapping: use templated isl types --- tc/core/polyhedral/schedule_tree_elem.cc | 3 ++- tc/core/polyhedral/schedule_tree_elem.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tc/core/polyhedral/schedule_tree_elem.cc b/tc/core/polyhedral/schedule_tree_elem.cc index 1e9584005..413458e91 100644 --- a/tc/core/polyhedral/schedule_tree_elem.cc +++ b/tc/core/polyhedral/schedule_tree_elem.cc @@ -142,7 +142,8 @@ ScheduleTreeMapping::ScheduleTreeMapping( auto id = kvp.first; // Create mapping filter by equating the // parameter mappedIds[i] to the "i"-th affine function. - upa = upa.sub(isl::union_pw_aff::param_on_domain(domain.universe(), id)); + upa = upa.sub( + isl::UnionPwAffOn::param_on_domain(domain.universe(), id)); filter_ = filter_.intersect(upa.zero_union_set()); } } diff --git a/tc/core/polyhedral/schedule_tree_elem.h b/tc/core/polyhedral/schedule_tree_elem.h index a912fab5c..f32cca862 100644 --- a/tc/core/polyhedral/schedule_tree_elem.h +++ b/tc/core/polyhedral/schedule_tree_elem.h @@ -179,7 +179,7 @@ struct ScheduleTreeMapping : public ScheduleTree { public: using Mapping = std::unordered_map< mapping::MappingId, - isl::union_pw_aff, + isl::UnionPwAffOn, typename mapping::MappingId::Hash>; static constexpr detail::ScheduleTreeType NodeType = From 323117c1c8f1370f724fc7de5e9c07b827d06b4b Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 44/85] extractDomainToIds: use templated isl types --- tc/core/polyhedral/cuda/mapped_scop.cc | 4 ++-- tc/core/polyhedral/schedule_utils-inl.h | 20 +++++++++++--------- tc/core/polyhedral/schedule_utils.h | 3 ++- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index 35523d0db..863e94f6a 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -536,7 +536,7 @@ isl::multi_union_pw_aff MappedScop::threadMappingSchedule( ids.emplace_back(mapping::ThreadId::makeId(i)); } auto tupleId = isl::id(tree->ctx_, kBlock); - return extractDomainToIds(scop_->scheduleRoot(), tree, ids, tupleId); + return extractDomainToIds(scop_->scheduleRoot(), tree, ids, tupleId); } isl::multi_union_pw_aff MappedScop::blockMappingSchedule( @@ -546,7 +546,7 @@ isl::multi_union_pw_aff MappedScop::blockMappingSchedule( ids.emplace_back(mapping::BlockId::makeId(i)); } auto tupleId = isl::id(tree->ctx_, kGrid); - return extractDomainToIds(scop_->scheduleRoot(), tree, ids, tupleId); + return extractDomainToIds(scop_->scheduleRoot(), tree, ids, tupleId); } Scop::SyncLevel MappedScop::findBestSync( diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index bacb9ccc4..f3eb0efdf 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -162,22 +162,24 @@ inline isl::MultiUnionPwAff partialScheduleMupa( * are assumed to have been mapped to these identifiers. * The result lives in a space of the form "tupleId"["ids"...]. */ -inline isl::multi_union_pw_aff extractDomainToIds( +template +isl::MultiUnionPwAff extractDomainToIds( const detail::ScheduleTree* root, const detail::ScheduleTree* tree, const std::vector& ids, isl::id tupleId) { using namespace polyhedral::detail; - auto space = isl::space(tree->ctx_, 0); - auto empty = isl::union_set::empty(space); - space = space.add_named_tuple_id_ui(tupleId, ids.size()); - auto zero = isl::multi_val::zero(space); - auto domainToIds = isl::multi_union_pw_aff(empty, zero); + auto paramSpace = isl::Space<>(tree->ctx_, 0); + auto empty = isl::UnionSet::empty(paramSpace); + auto space = + paramSpace.add_named_tuple_id_ui(tupleId, ids.size()); + auto zero = isl::MultiVal::zero(space); + auto domainToIds = isl::MultiUnionPwAff(empty, zero); for (auto mapping : tree->collect(tree, ScheduleTreeType::Mapping)) { auto mappingNode = mapping->as(); - auto list = isl::union_pw_aff_list(tree->ctx_, ids.size()); + auto list = isl::UnionPwAffListOn(tree->ctx_, ids.size()); for (auto id : ids) { if (mappingNode->mapping.count(id) == 0) { break; @@ -189,8 +191,8 @@ inline isl::multi_union_pw_aff extractDomainToIds( if (static_cast(list.size()) != ids.size()) { continue; } - auto nodeToIds = isl::multi_union_pw_aff(space, list); - auto active = activeDomainPoints(root, mapping); + auto nodeToIds = isl::MultiUnionPwAff(space, list); + auto active = isl::UnionSet(activeDomainPoints(root, mapping)); TC_CHECK(active.intersect(domainToIds.domain()).is_empty()) << "conflicting mappings; are the filters in the tree disjoint?"; nodeToIds = nodeToIds.intersect_domain(active); diff --git a/tc/core/polyhedral/schedule_utils.h b/tc/core/polyhedral/schedule_utils.h index 989df9da2..2b5829412 100644 --- a/tc/core/polyhedral/schedule_utils.h +++ b/tc/core/polyhedral/schedule_utils.h @@ -121,7 +121,8 @@ isl::union_set prefixMappingFilter( // rooted at "root") to identifiers "ids", where all branches in "tree" are // assumed to have been mapped to these identifiers. The result lives in a // space of the form "tupleId"["ids"...]. -isl::multi_union_pw_aff extractDomainToIds( +template +isl::MultiUnionPwAff extractDomainToIds( const detail::ScheduleTree* root, const detail::ScheduleTree* tree, const std::vector& ids, From 97290f8a29666a3601d565b62cd8036647cf788c Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 45/85] MappedScop::threadMappingSchedule: use templated isl types --- tc/core/polyhedral/cuda/mapped_scop.cc | 2 +- tc/core/polyhedral/cuda/mapped_scop.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index 863e94f6a..721c1ec83 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -529,7 +529,7 @@ isl::MultiAff constructThreadToWarp( } } // namespace -isl::multi_union_pw_aff MappedScop::threadMappingSchedule( +isl::MultiUnionPwAff MappedScop::threadMappingSchedule( const ScheduleTree* tree) const { std::vector ids; for (size_t i = 0; i < numThreads.view.size(); ++i) { diff --git a/tc/core/polyhedral/cuda/mapped_scop.h b/tc/core/polyhedral/cuda/mapped_scop.h index 37c5426e0..0da838973 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.h +++ b/tc/core/polyhedral/cuda/mapped_scop.h @@ -210,7 +210,7 @@ class MappedScop { // to the thread identifiers, where all branches in "tree" // are assumed to have been mapped to thread identifiers. // The result lives in a space of the form block[x, ...]. - isl::multi_union_pw_aff threadMappingSchedule( + isl::MultiUnionPwAff threadMappingSchedule( const detail::ScheduleTree* tree) const; // Extract a mapping from the domain elements active at "tree" From e46da35957abc0afb9a883c9f0ce4c49f1eef5e8 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 46/85] MappedScop::blockMappingSchedule: use templated isl types --- tc/core/polyhedral/cuda/mapped_scop.cc | 2 +- tc/core/polyhedral/cuda/mapped_scop.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index 721c1ec83..16a500010 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -539,7 +539,7 @@ isl::MultiUnionPwAff MappedScop::threadMappingSchedule( return extractDomainToIds(scop_->scheduleRoot(), tree, ids, tupleId); } -isl::multi_union_pw_aff MappedScop::blockMappingSchedule( +isl::MultiUnionPwAff MappedScop::blockMappingSchedule( const ScheduleTree* tree) const { std::vector ids; for (size_t i = 0; i < numBlocks.view.size(); ++i) { diff --git a/tc/core/polyhedral/cuda/mapped_scop.h b/tc/core/polyhedral/cuda/mapped_scop.h index 0da838973..c971b80e9 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.h +++ b/tc/core/polyhedral/cuda/mapped_scop.h @@ -217,7 +217,7 @@ class MappedScop { // to the block identifiers, where all branches in "tree" // are assumed to have been mapped to block identifiers. // The result lives in a space of the form grid[x, ...]. - isl::multi_union_pw_aff blockMappingSchedule( + isl::MultiUnionPwAff blockMappingSchedule( const detail::ScheduleTree* tree) const; private: From 5efdcde5dcc2e591c5173c3af324784596e762b2 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 47/85] Scop::makeIslAffFromStmtExpr: use templated isl types --- tc/core/polyhedral/scop.cc | 10 +++++----- tc/core/polyhedral/scop.h | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tc/core/polyhedral/scop.cc b/tc/core/polyhedral/scop.cc index 5490a32cb..e8ac4c0e1 100644 --- a/tc/core/polyhedral/scop.cc +++ b/tc/core/polyhedral/scop.cc @@ -516,12 +516,12 @@ const Halide::OutputImageParam& Scop::findArgument(isl::id id) const { return *halide.inputs.begin(); } -isl::aff Scop::makeIslAffFromStmtExpr(isl::id stmtId, const Halide::Expr& e) - const { +isl::AffOn Scop::makeIslAffFromStmtExpr( + isl::id stmtId, + const Halide::Expr& e) const { auto domain = halide.domains.at(stmtId); - isl::aff aff = halide2isl::makeIslAffFromExpr(domain.paramSpace, e); - aff = aff.unbind_params_insert_domain(domain.tuple); - return aff; + auto aff = halide2isl::makeIslAffFromExpr(domain.paramSpace, e); + return aff.unbind_params_insert_domain(domain.tuple); } } // namespace polyhedral diff --git a/tc/core/polyhedral/scop.h b/tc/core/polyhedral/scop.h index 6b2ebc06f..15fcd615c 100644 --- a/tc/core/polyhedral/scop.h +++ b/tc/core/polyhedral/scop.h @@ -424,7 +424,9 @@ struct Scop { // Return a null isl::aff if the expression is not affine. Fail if any // of the variables does not correspond to a parameter or // an instance identifier of the statement. - isl::aff makeIslAffFromStmtExpr(isl::id stmtId, const Halide::Expr& e) const; + isl::AffOn makeIslAffFromStmtExpr( + isl::id stmtId, + const Halide::Expr& e) const; // Promote a tensor reference group to a storage of a given "kind", // inserting the copy From 30d7568e3ef5362457e01c0a4294737e5bcdbc09 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 48/85] activeDomainPoints: cast result to templated isl type At the same time, turn off automatic type deduction in the callers of activeDomainPoints. This allows these callers to gradually move to templated isl types. The cast itself is removed after the schedule tree has been converted to templated isl types. --- tc/core/polyhedral/cuda/mapped_scop.cc | 4 ++-- tc/core/polyhedral/schedule_transforms.cc | 12 ++++++++---- tc/core/polyhedral/schedule_utils-inl.h | 2 +- tc/core/polyhedral/schedule_utils.cc | 5 +++-- tc/core/polyhedral/schedule_utils.h | 2 +- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index 16a500010..df70b7a69 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -230,7 +230,7 @@ bool separatedOut( Scop& scop, ScheduleTree* tree, isl::UnionSet updates) { - auto domain = activeDomainPoints(scop.scheduleRoot(), tree); + isl::union_set domain = activeDomainPoints(scop.scheduleRoot(), tree); auto other = domain.subtract(updates); if (other.is_empty()) { return true; @@ -344,7 +344,7 @@ ScheduleTree* MappedScop::separateReduction(ScheduleTree* st) { reductionBandUpdates_.at(reduction).separated = true; auto root = scop_->scheduleRoot(); - auto domain = activeDomainPoints(root, st); + isl::union_set domain = activeDomainPoints(root, st); auto prefixSchedule = prefixScheduleMupa(root, st); auto reductionSchedule = reductionMapSchedule(st); auto space = reductionSchedule.get_space(); diff --git a/tc/core/polyhedral/schedule_transforms.cc b/tc/core/polyhedral/schedule_transforms.cc index bd054cfd2..8fb19387f 100644 --- a/tc/core/polyhedral/schedule_transforms.cc +++ b/tc/core/polyhedral/schedule_transforms.cc @@ -570,7 +570,8 @@ bool canOrderBefore( ScheduleTree* tree, isl::union_set filter, isl::union_map dependences) { - auto other = activeDomainPoints(root, tree).subtract(filter); + isl::union_set active = activeDomainPoints(root, tree); + auto other = active.subtract(filter); return canOrder(filter, other, dependences); } @@ -579,7 +580,8 @@ bool canOrderAfter( ScheduleTree* tree, isl::union_set filter, isl::union_map dependences) { - auto other = activeDomainPoints(root, tree).subtract(filter); + isl::union_set active = activeDomainPoints(root, tree); + auto other = active.subtract(filter); return canOrder(other, filter, dependences); } @@ -587,7 +589,8 @@ void orderBefore( ScheduleTree* root, ScheduleTree* tree, isl::union_set filter) { - auto other = activeDomainPoints(root, tree).subtract(filter); + isl::union_set active = activeDomainPoints(root, tree); + auto other = active.subtract(filter); auto seq = ScheduleTree::makeSequence( gistedFilter(filter, ScheduleTree::makeScheduleTree(*tree))); auto parent = tree->ancestor(root, 1); @@ -597,7 +600,8 @@ void orderBefore( } void orderAfter(ScheduleTree* root, ScheduleTree* tree, isl::union_set filter) { - auto other = activeDomainPoints(root, tree).subtract(filter); + isl::union_set active = activeDomainPoints(root, tree); + auto other = active.subtract(filter); auto seq = ScheduleTree::makeSequence( gistedFilter(filter, ScheduleTree::makeScheduleTree(*tree))); auto parent = tree->ancestor(root, 1); diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index f3eb0efdf..e3e096144 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -192,7 +192,7 @@ isl::MultiUnionPwAff extractDomainToIds( continue; } auto nodeToIds = isl::MultiUnionPwAff(space, list); - auto active = isl::UnionSet(activeDomainPoints(root, mapping)); + auto active = activeDomainPoints(root, mapping); TC_CHECK(active.intersect(domainToIds.domain()).is_empty()) << "conflicting mappings; are the filters in the tree disjoint?"; nodeToIds = nodeToIds.intersect_domain(active); diff --git a/tc/core/polyhedral/schedule_utils.cc b/tc/core/polyhedral/schedule_utils.cc index 6ff67fa95..0576231b3 100644 --- a/tc/core/polyhedral/schedule_utils.cc +++ b/tc/core/polyhedral/schedule_utils.cc @@ -93,10 +93,11 @@ isl::union_set prefixMappingFilter( return collectDomain(root, node->ancestors(root), &applyMapping); } -isl::union_set activeDomainPoints( +isl::UnionSet activeDomainPoints( const ScheduleTree* root, const ScheduleTree* node) { - return activeDomainPointsHelper(root, node->ancestors(root)); + return isl::UnionSet( + activeDomainPointsHelper(root, node->ancestors(root))); } isl::union_set activeDomainPointsBelow( diff --git a/tc/core/polyhedral/schedule_utils.h b/tc/core/polyhedral/schedule_utils.h index 2b5829412..ac627e1cf 100644 --- a/tc/core/polyhedral/schedule_utils.h +++ b/tc/core/polyhedral/schedule_utils.h @@ -99,7 +99,7 @@ isl::MultiUnionPwAff partialScheduleMupa( // point is active if it was not filtered away on the path from the // root to the node. The root must be a domain element, otherwise no // elements would be considered active. -isl::union_set activeDomainPoints( +isl::UnionSet activeDomainPoints( const detail::ScheduleTree* root, const detail::ScheduleTree* node); From 2280cf4da660c6051ded867f0d8df596163a0271 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 49/85] activeDomainPointsBelow: cast result to templated isl type At the same time, turn off automatic type deduction in the accessSubscriptsAreUnrolledLoops caller of activeDomainPointsBelow. This allows this caller to move to templated isl types separately. The cast itself is removed after the schedule tree has been converted to templated isl types. --- tc/core/polyhedral/cuda/memory_promotion_heuristic.cc | 2 +- tc/core/polyhedral/schedule_utils.cc | 4 ++-- tc/core/polyhedral/schedule_utils.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index 5a9ba792f..576e28305 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -312,7 +312,7 @@ bool accessSubscriptsAreUnrolledLoops( for (auto leaf : leaves) { auto ancestors = leaf->ancestors(root); ancestors.push_back(leaf); - auto subdomain = activeDomainPointsBelow(root, leaf); + isl::union_set subdomain = activeDomainPointsBelow(root, leaf); auto unrolledDims = isl::union_pw_aff_list(leaf->ctx_, 1); for (auto node : ancestors) { diff --git a/tc/core/polyhedral/schedule_utils.cc b/tc/core/polyhedral/schedule_utils.cc index 0576231b3..e6b1745cf 100644 --- a/tc/core/polyhedral/schedule_utils.cc +++ b/tc/core/polyhedral/schedule_utils.cc @@ -100,12 +100,12 @@ isl::UnionSet activeDomainPoints( activeDomainPointsHelper(root, node->ancestors(root))); } -isl::union_set activeDomainPointsBelow( +isl::UnionSet activeDomainPointsBelow( const ScheduleTree* root, const ScheduleTree* node) { auto ancestors = node->ancestors(root); ancestors.emplace_back(node); - return activeDomainPointsHelper(root, ancestors); + return isl::UnionSet(activeDomainPointsHelper(root, ancestors)); } vector collectScheduleTreesPath( diff --git a/tc/core/polyhedral/schedule_utils.h b/tc/core/polyhedral/schedule_utils.h index ac627e1cf..f09f8c1b6 100644 --- a/tc/core/polyhedral/schedule_utils.h +++ b/tc/core/polyhedral/schedule_utils.h @@ -107,7 +107,7 @@ isl::UnionSet activeDomainPoints( // point is active if it was not filtered away on the path from the // root to the node. The root must be a domain element, otherwise no // elements would be considered active. -isl::union_set activeDomainPointsBelow( +isl::UnionSet activeDomainPointsBelow( const detail::ScheduleTree* root, const detail::ScheduleTree* node); From 9f8a96a43ac81647935690ceb204e7eeefe93061 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 50/85] MappedScop::findBestSync: temporarily remove type deduction This allows Scop::dependences to be converted to templated isl types without having to convert MappedScop::findBestSync at the same time. Automatic type deduction will be reintroduced when MappedScop::findBestSync is converted. --- tc/core/polyhedral/cuda/mapped_scop.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index df70b7a69..5432a40e2 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -560,7 +560,7 @@ Scop::SyncLevel MappedScop::findBestSync( auto activePoints2 = activeDomainPointsBelow(stRoot, st2); // The dependences between the two schedule trees - auto dependences = scop_->dependences; + isl::union_map dependences = scop_->dependences; dependences = dependences.intersect_domain(activePoints1); dependences = dependences.intersect_range(activePoints2); if (dependences.is_empty()) { From 8e64b26f739a9689aa2d9e4a2a46e08bd6b722a8 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 51/85] Scop::dependences: use templated isl types --- tc/core/polyhedral/cuda/mapped_scop.cc | 2 +- tc/core/polyhedral/scop.cc | 11 ++++++----- tc/core/polyhedral/scop.h | 5 +++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index 5432a40e2..adf52600e 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -230,7 +230,7 @@ bool separatedOut( Scop& scop, ScheduleTree* tree, isl::UnionSet updates) { - isl::union_set domain = activeDomainPoints(scop.scheduleRoot(), tree); + auto domain = activeDomainPoints(scop.scheduleRoot(), tree); auto other = domain.subtract(updates); if (other.is_empty()) { return true; diff --git a/tc/core/polyhedral/scop.cc b/tc/core/polyhedral/scop.cc index e8ac4c0e1..2158a1be0 100644 --- a/tc/core/polyhedral/scop.cc +++ b/tc/core/polyhedral/scop.cc @@ -300,11 +300,11 @@ namespace { using namespace tc::polyhedral; -isl::union_map computeDependences( - isl::union_map sources, - isl::union_map sinks, +isl::UnionMap computeDependences( + isl::UnionMap sources, + isl::UnionMap sinks, isl::schedule schedule) { - auto uai = isl::union_access_info(sinks); + auto uai = sinks.asUnionAccessInfo(); uai = uai.set_may_source(sources); uai = uai.set_schedule(schedule); auto flow = uai.compute_flow(); @@ -369,7 +369,8 @@ void Scop::computeAllDependences() { dependences = flowDeps.unite(falseDeps).coalesce(); } -isl::union_map Scop::activeDependences(detail::ScheduleTree* tree) { +isl::UnionMap Scop::activeDependences( + detail::ScheduleTree* tree) { auto prefix = prefixScheduleMupa(scheduleRoot(), tree); auto domain = activeDomainPoints(scheduleRoot(), tree); auto active = dependences; diff --git a/tc/core/polyhedral/scop.h b/tc/core/polyhedral/scop.h index 15fcd615c..20cc58896 100644 --- a/tc/core/polyhedral/scop.h +++ b/tc/core/polyhedral/scop.h @@ -488,7 +488,8 @@ struct Scop { void computeAllDependences(); // Return the set of dependences that are active // at the given position. - isl::union_map activeDependences(detail::ScheduleTree* tree); + isl::UnionMap activeDependences( + detail::ScheduleTree* tree); public: // Halide stuff @@ -520,7 +521,7 @@ struct Scop { Body body; // RAW, WAR, and WAW dependences - isl::union_map dependences; + isl::UnionMap dependences; private: // By analogy with generalized functions, a ScheduleTree is a (piecewise From bfdf31d17ab26db924bc2cc876da540f08c64484 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 52/85] partialTargetTiles: use templated isl types --- tc/core/CMakeLists.txt | 1 - tc/core/polyhedral/cuda/mapped_scop.cc | 2 +- .../{separation.cc => separation-inl.h} | 24 ++++++++++--------- tc/core/polyhedral/separation.h | 15 ++++++++---- 4 files changed, 24 insertions(+), 18 deletions(-) rename tc/core/polyhedral/{separation.cc => separation-inl.h} (75%) diff --git a/tc/core/CMakeLists.txt b/tc/core/CMakeLists.txt index 8842ff7cf..61ff92d8c 100644 --- a/tc/core/CMakeLists.txt +++ b/tc/core/CMakeLists.txt @@ -32,7 +32,6 @@ add_library( polyhedral/schedule_print.cc polyhedral/schedule_utils.cc polyhedral/scop.cc - polyhedral/separation.cc polyhedral/unroll.cc polyhedral/utils.cc ) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index adf52600e..623626369 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -344,7 +344,7 @@ ScheduleTree* MappedScop::separateReduction(ScheduleTree* st) { reductionBandUpdates_.at(reduction).separated = true; auto root = scop_->scheduleRoot(); - isl::union_set domain = activeDomainPoints(root, st); + auto domain = activeDomainPoints(root, st); auto prefixSchedule = prefixScheduleMupa(root, st); auto reductionSchedule = reductionMapSchedule(st); auto space = reductionSchedule.get_space(); diff --git a/tc/core/polyhedral/separation.cc b/tc/core/polyhedral/separation-inl.h similarity index 75% rename from tc/core/polyhedral/separation.cc rename to tc/core/polyhedral/separation-inl.h index c5d38436e..d9d62c44f 100644 --- a/tc/core/polyhedral/separation.cc +++ b/tc/core/polyhedral/separation-inl.h @@ -13,35 +13,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#pragma once -#include "tc/core/polyhedral/separation.h" #include "tc/core/check.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/external/isl.h" namespace tc { namespace polyhedral { -isl::union_set partialTargetTiles( - isl::union_set domain, - isl::multi_union_pw_aff prefix, - isl::multi_union_pw_aff pretile, - isl::multi_val size) { +template +isl::UnionSet partialTargetTiles( + isl::UnionSet domain, + isl::MultiUnionPwAff prefix, + isl::MultiUnionPwAff pretile, + isl::MultiVal size) { auto space = pretile.get_space(); - auto tile = isl::multi_aff::identity(space.map_from_set()); + auto tile = isl::MultiAff::identity(space.map_from_set()); tile = tile.scale_down(size).floor(); - auto tileMap = isl::map(tile); + auto tileMap = tile.asMap(); // Relation between pairs of elements in the same target tile. - auto sameTile = isl::union_map(tileMap.apply_range(tileMap.reverse())); + auto sameTile = tileMap.apply_range(tileMap.reverse()).asUnionMap(); // Mapping between domain elements and pairs of prefix and target values. // D -> [P -> T] auto schedule = prefix.range_product(pretile); - auto scheduleMap = isl::union_map::from(schedule); + auto scheduleMap = schedule.toUnionMap(); // Mapping between prefix values and target values // for some common domain element // P -> T TC_CHECK(domain.is_subset(scheduleMap.domain())); - auto target = domain.apply(scheduleMap).unwrap(); + auto target = domain.apply(scheduleMap).template unwrap(); // Mapping between prefix values and target values // for some common domain element, extended to complete target tiles. // P -> Tc diff --git a/tc/core/polyhedral/separation.h b/tc/core/polyhedral/separation.h index 668db7c93..a08c8b50d 100644 --- a/tc/core/polyhedral/separation.h +++ b/tc/core/polyhedral/separation.h @@ -15,6 +15,8 @@ */ #pragma once +#include "tc/core/polyhedral/domain_types.h" + #include "tc/external/isl.h" namespace tc { @@ -25,11 +27,14 @@ namespace polyhedral { * Return the elements in "domain" that map to partial tiles * in this space for fixed values of "prefix". */ -isl::union_set partialTargetTiles( - isl::union_set domain, - isl::multi_union_pw_aff prefix, - isl::multi_union_pw_aff pretile, - isl::multi_val size); +template +isl::UnionSet partialTargetTiles( + isl::UnionSet domain, + isl::MultiUnionPwAff prefix, + isl::MultiUnionPwAff pretile, + isl::MultiVal size); } // namespace polyhedral } // namespace tc + +#include "tc/core/polyhedral/separation-inl.h" From a396fcd6c62bc721a86b0be8d962032e423968ef Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 53/85] canOrder*: use templated isl types --- tc/core/polyhedral/schedule_transforms.cc | 28 ++++++++++++----------- tc/core/polyhedral/schedule_transforms.h | 9 ++++---- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/tc/core/polyhedral/schedule_transforms.cc b/tc/core/polyhedral/schedule_transforms.cc index 8fb19387f..a90972294 100644 --- a/tc/core/polyhedral/schedule_transforms.cc +++ b/tc/core/polyhedral/schedule_transforms.cc @@ -31,6 +31,7 @@ #include "tc/core/check.h" #include "tc/core/constants.h" #include "tc/core/functional.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/mapping_types.h" #include "tc/core/polyhedral/schedule_tree_elem.h" #include "tc/core/polyhedral/schedule_tree_matcher.h" @@ -544,19 +545,20 @@ ScheduleTreeUPtr gistedFilter(isl::union_set filter, ScheduleTreeUPtr child) { * without violating any of the (active) "dependences"? */ bool canOrder( - isl::union_set first, - isl::union_set second, - isl::union_map dependences) { + isl::UnionSet first, + isl::UnionSet second, + isl::UnionMap dependences) { if (first.is_empty() || second.is_empty()) { return true; } // Create an ordering schedule function first -> 0; second -> 1. auto ctx = dependences.get_ctx(); - auto space = isl::space(ctx, 0).add_unnamed_tuple_ui(1); - auto zero = isl::multi_val::zero(space); + auto space = isl::Space<>(ctx, 0).add_unnamed_tuple_ui(1); + auto zero = isl::MultiVal::zero(space); auto one = zero.set_val(0, isl::val::one(ctx)); - auto order = isl::multi_union_pw_aff(first, zero); - order = order.union_add(isl::multi_union_pw_aff(second, one)); + auto order = isl::MultiUnionPwAff(first, zero); + order = order.union_add( + isl::MultiUnionPwAff(second, one)); // Check that this ordering preserves all dependences. auto preserved = dependences.lex_lt_at(order).unite(dependences.eq_at(order)); @@ -568,9 +570,9 @@ bool canOrder( bool canOrderBefore( ScheduleTree* root, ScheduleTree* tree, - isl::union_set filter, - isl::union_map dependences) { - isl::union_set active = activeDomainPoints(root, tree); + isl::UnionSet filter, + isl::UnionMap dependences) { + auto active = activeDomainPoints(root, tree); auto other = active.subtract(filter); return canOrder(filter, other, dependences); } @@ -578,9 +580,9 @@ bool canOrderBefore( bool canOrderAfter( ScheduleTree* root, ScheduleTree* tree, - isl::union_set filter, - isl::union_map dependences) { - isl::union_set active = activeDomainPoints(root, tree); + isl::UnionSet filter, + isl::UnionMap dependences) { + auto active = activeDomainPoints(root, tree); auto other = active.subtract(filter); return canOrder(other, filter, dependences); } diff --git a/tc/core/polyhedral/schedule_transforms.h b/tc/core/polyhedral/schedule_transforms.h index add33d7f2..4f743d2c7 100644 --- a/tc/core/polyhedral/schedule_transforms.h +++ b/tc/core/polyhedral/schedule_transforms.h @@ -22,6 +22,7 @@ #include #include "tc/core/functional.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/mapping_types.h" #include "tc/core/polyhedral/options.h" #include "tc/core/polyhedral/schedule_tree.h" @@ -233,16 +234,16 @@ void insertExtensionLabelAfter( bool canOrderBefore( detail::ScheduleTree* root, detail::ScheduleTree* tree, - isl::union_set filter, - isl::union_map dependences); + isl::UnionSet filter, + isl::UnionMap dependences); // Is it possible to order the elements in the given filter // after the other active elements without violating // any of the given dependences? bool canOrderAfter( detail::ScheduleTree* root, detail::ScheduleTree* tree, - isl::union_set filter, - isl::union_map dependences); + isl::UnionSet filter, + isl::UnionMap dependences); // Insert a sequence to ensure that the active domain elements // in the given filter are executed before the other active domain elements. From 43b833822feac8d5f322a2f1b8aae0aa0452a7cf Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 54/85] order*: use templated isl types --- tc/core/polyhedral/schedule_transforms.cc | 11 +++++++---- tc/core/polyhedral/schedule_transforms.h | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tc/core/polyhedral/schedule_transforms.cc b/tc/core/polyhedral/schedule_transforms.cc index a90972294..c8f4d6f20 100644 --- a/tc/core/polyhedral/schedule_transforms.cc +++ b/tc/core/polyhedral/schedule_transforms.cc @@ -590,8 +590,8 @@ bool canOrderAfter( void orderBefore( ScheduleTree* root, ScheduleTree* tree, - isl::union_set filter) { - isl::union_set active = activeDomainPoints(root, tree); + isl::UnionSet filter) { + auto active = activeDomainPoints(root, tree); auto other = active.subtract(filter); auto seq = ScheduleTree::makeSequence( gistedFilter(filter, ScheduleTree::makeScheduleTree(*tree))); @@ -601,8 +601,11 @@ void orderBefore( parent->insertChild(childPos, std::move(seq)); } -void orderAfter(ScheduleTree* root, ScheduleTree* tree, isl::union_set filter) { - isl::union_set active = activeDomainPoints(root, tree); +void orderAfter( + ScheduleTree* root, + ScheduleTree* tree, + isl::UnionSet filter) { + auto active = activeDomainPoints(root, tree); auto other = active.subtract(filter); auto seq = ScheduleTree::makeSequence( gistedFilter(filter, ScheduleTree::makeScheduleTree(*tree))); diff --git a/tc/core/polyhedral/schedule_transforms.h b/tc/core/polyhedral/schedule_transforms.h index 4f743d2c7..6820792b4 100644 --- a/tc/core/polyhedral/schedule_transforms.h +++ b/tc/core/polyhedral/schedule_transforms.h @@ -250,13 +250,13 @@ bool canOrderAfter( void orderBefore( detail::ScheduleTree* root, detail::ScheduleTree* tree, - isl::union_set filter); + isl::UnionSet filter); // Insert a sequence to ensure that the active domain elements // in the given filter are executed after the other active domain elements. void orderAfter( detail::ScheduleTree* root, detail::ScheduleTree* tree, - isl::union_set filter); + isl::UnionSet filter); } // namespace polyhedral } // namespace tc From 04299eff0de4cd5e3811b6cd064a06c85defaa49 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Fri, 27 Jul 2018 16:38:16 +0200 Subject: [PATCH 55/85] collectMappingsTo: cast result to templated isl type This allows callers of collectMappingsTo to move to templated isl types. The case will be removed after the schedule tree has been converted to templated isl types. --- tc/core/polyhedral/cuda/memory_promotion_heuristic.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index 576e28305..375a78c40 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -248,7 +248,7 @@ bool promotionImprovesCoalescing( * Returns the union of all mapping filters to "MappingType" in "scop". */ template -isl::union_set collectMappingsTo(const Scop& scop) { +isl::UnionSet collectMappingsTo(const Scop& scop) { auto root = scop.scheduleRoot(); auto domain = scop.domain(); auto mappingFilters = @@ -260,7 +260,7 @@ isl::union_set collectMappingsTo(const Scop& scop) { auto filter = filterNode->filter_.intersect(activeDomainPoints(root, mf)); mapping = mapping.unite(filterNode->filter_); } - return mapping; + return isl::UnionSet(mapping); } /* @@ -472,7 +472,7 @@ void promoteToSharedBelow( throw promotion::IncorrectScope("cannot promote below a sequence/set node"); } - isl::union_map partialSched = partialSchedule(root, node); + auto partialSched = partialSchedule(root, node); auto mapping = collectMappingsTo(scop); auto groupMap = TensorReferenceGroup::accessedWithin( @@ -646,7 +646,7 @@ void promoteToRegistersBelow(MappedScop& mscop, detail::ScheduleTree* scope) { auto blockMapping = collectMappingsTo(scop); auto mapping = collectMappingsTo(scop).intersect(blockMapping); - isl::union_map schedule = partialSchedule(scop.scheduleRoot(), scope); + auto schedule = partialSchedule(scop.scheduleRoot(), scope); auto groupMap = TensorReferenceGroup::accessedWithin( schedule.intersect_domain(mapping), scop.body); From 73421468b7f8a77b18ea8b38adf272b2aa35cbf6 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Fri, 27 Jul 2018 21:42:34 +0200 Subject: [PATCH 56/85] accessedWithin: use templated isl types --- tc/core/polyhedral/memory_promotion.cc | 3 ++- tc/core/polyhedral/memory_promotion.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index e5741c5b4..a5a8c7cfb 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -22,6 +22,7 @@ #include "tc/core/check.h" #include "tc/core/polyhedral/body.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/exceptions.h" #include "tc/core/polyhedral/schedule_tree.h" #include "tc/core/polyhedral/scop.h" @@ -342,7 +343,7 @@ void addSingletonReferenceGroups( // TensorReferenceGroup, with each group potentially containing multiple // references. TensorGroups TensorReferenceGroup::accessedWithin( - isl::union_map outerSchedule, + isl::UnionMap outerSchedule, const Body& body) { TensorGroups tensorGroups; auto domain = outerSchedule.domain(); diff --git a/tc/core/polyhedral/memory_promotion.h b/tc/core/polyhedral/memory_promotion.h index 8ada806aa..cc402a6c8 100644 --- a/tc/core/polyhedral/memory_promotion.h +++ b/tc/core/polyhedral/memory_promotion.h @@ -17,6 +17,7 @@ #include +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_tree.h" #include "tc/core/polyhedral/scop.h" #include "tc/external/isl.h" @@ -112,7 +113,7 @@ class TensorReferenceGroup { public: static TensorGroups accessedWithin( - isl::union_map outerSchedule, + isl::UnionMap outerSchedule, const Body& body); bool isReadOnly() const; From 4cba4505e47b8da1e179c43b5a46eef9f4088583 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Mon, 30 Jul 2018 14:56:17 +0200 Subject: [PATCH 57/85] addSingletonReferenceGroups: use templated isl types --- tc/core/polyhedral/memory_promotion.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index a5a8c7cfb..498f21a9f 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -295,16 +295,16 @@ void addSingletonReferenceGroup( void addSingletonReferenceGroups( TensorGroups& tensorGroups, - isl::union_map accesses, - isl::union_set domain, - isl::union_map schedule, + isl::UnionMap, Tensor> accesses, + isl::UnionSet domain, + isl::UnionMap schedule, AccessType type) { // access relations have a shape :: [D -> ref] -> O // use currying to isolate the D part before intersecting with the domain // Compute initial groups with single reference per group. std::unordered_set unapproximatable; for (auto a : accesses.get_map_list()) { - if (isl::union_map(a.curry()).intersect_domain(domain).is_empty()) { + if (a.curry().asUnionMap().intersect_domain(domain).is_empty()) { continue; } From 8e7cce0c303124d73e5da7bf5d6ea38386bc089b Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Mon, 30 Jul 2018 15:33:51 +0200 Subject: [PATCH 58/85] addSingletonReferenceGroup: use templated isl types --- tc/core/polyhedral/memory_promotion.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index 498f21a9f..c598f8bfc 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -282,13 +282,12 @@ void joinOverlappingWrites( void addSingletonReferenceGroup( TensorGroups& tensorGroups, isl::id targetTensor, - isl::union_map schedule, - isl::map access, + isl::UnionMap schedule, + isl::Map, Tensor> access, AccessType type) { - auto scopedUnionAccess = isl::union_map(access.curry()); - scopedUnionAccess = scopedUnionAccess.apply_domain(schedule); - auto scopedAccess = isl::map::from(scopedUnionAccess); - scopedAccess = scopedAccess.uncurry(); + auto unionAccess = access.curry().asUnionMap(); + auto scopedUnionAccess = unionAccess.apply_domain(schedule); + auto scopedAccess = scopedUnionAccess.toMap().uncurry(); tensorGroups[targetTensor].push_back( TensorReferenceGroup::makeSingleton(access, scopedAccess, type)); } From 18d5d022092243357dc41073c031eabf5a714e02 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Mon, 30 Jul 2018 15:51:01 +0200 Subject: [PATCH 59/85] makeSingleton: use templated isl types --- tc/core/polyhedral/memory_promotion.cc | 8 ++++---- tc/core/polyhedral/memory_promotion.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index c598f8bfc..ffcba9e31 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -85,13 +85,13 @@ ScopedFootprint outputRanges(isl::map access) { // Access has the shape :: [S -> ref] -> O // Extract the reference ID, store it separately and simplify the access. std::unique_ptr TensorReferenceGroup::makeSingleton( - isl::map originalAccess, - isl::map scopedAccess, + isl::Map, Tensor> originalAccess, + isl::Map, Tensor> scopedTaggedAccess, AccessType type) { auto ref = std::unique_ptr(new TensorReference); auto refId = - scopedAccess.get_space().domain().unwrap().get_map_range_tuple_id(); - scopedAccess = scopedAccess.domain_factor_domain(); + scopedTaggedAccess.get_space().domain().unwrap().get_map_range_tuple_id(); + auto scopedAccess = scopedTaggedAccess.domain_factor_domain(); ref->originalAccess = originalAccess.domain_factor_domain(); ref->scopedAccess = scopedAccess; ref->type = type; diff --git a/tc/core/polyhedral/memory_promotion.h b/tc/core/polyhedral/memory_promotion.h index cc402a6c8..b0e4dea56 100644 --- a/tc/core/polyhedral/memory_promotion.h +++ b/tc/core/polyhedral/memory_promotion.h @@ -156,8 +156,8 @@ class TensorReferenceGroup { std::unique_ptr&& g1, std::unique_ptr&& g2); static std::unique_ptr makeSingleton( - isl::map originalAccess, - isl::map scopedAccess, + isl::Map, Tensor> originalAccess, + isl::Map, Tensor> scopedAccess, AccessType type); public: From 6fb5fc9dadbc0b4f9a3c70f85c2ed115e4990fa5 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Mon, 30 Jul 2018 15:56:42 +0200 Subject: [PATCH 60/85] TensorReference: use templated isl types --- tc/core/polyhedral/memory_promotion.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.h b/tc/core/polyhedral/memory_promotion.h index b0e4dea56..dd8ec9c89 100644 --- a/tc/core/polyhedral/memory_promotion.h +++ b/tc/core/polyhedral/memory_promotion.h @@ -81,11 +81,11 @@ class TensorReference { public: // Original access relation in terms of the Scop domain. - isl::map originalAccess; + isl::Map originalAccess; // Access relation in terms of partial schedule at the point where the // reference group is introduced in the tree. - isl::map scopedAccess; + isl::Map scopedAccess; // Access direction (read or write). AccessType type; From ed3a6f3c9ddc439696c5f7a4ecd685a92e0115d6 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 61/85] tensorElementsSet: use templated isl types --- tc/core/polyhedral/memory_promotion.cc | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index ffcba9e31..841b9882f 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -408,25 +408,26 @@ namespace { // each dimension of the tensor is contrained by the min_aff on the left and // by the min_aff + extent_aff on the right. Intersect this set with the // context of the scop. -isl::set tensorElementsSet(const Scop& scop, isl::id tensorId) { +isl::Set tensorElementsSet(const Scop& scop, isl::id tensorId) { auto halideParameter = scop.findArgument(tensorId).parameter(); auto space = scop.domain().get_space(); auto nDim = halideParameter.dimensions(); auto tensorTuple = constructTensorTuple(space, tensorId, nDim); auto tensorSpace = tensorTuple.get_space(); - auto tensorElements = isl::set::universe(tensorSpace); - auto identity = isl::multi_aff::identity(tensorSpace.map_from_set()); + auto tensorElements = isl::Set::universe(tensorSpace); + auto identity = + isl::MultiAff::identity(tensorSpace.map_from_set()); for (int i = 0; i < nDim; ++i) { - isl::aff minAff = halide2isl::makeIslAffFromExpr( + auto minAff = halide2isl::makeIslAffFromExpr( space, halideParameter.min_constraint(i)); - isl::aff extentAff = halide2isl::makeIslAffFromExpr( + auto extentAff = halide2isl::makeIslAffFromExpr( space, halideParameter.extent_constraint(i)); - minAff = minAff.unbind_params_insert_domain(tensorTuple); - extentAff = extentAff.unbind_params_insert_domain(tensorTuple); + auto minAff2 = minAff.unbind_params_insert_domain(tensorTuple); + auto extentAff2 = extentAff.unbind_params_insert_domain(tensorTuple); auto aff = identity.get_aff(i); - tensorElements = tensorElements & (minAff <= isl::aff_set(aff)) & - (isl::aff_set(aff) < (minAff + extentAff)); + tensorElements = tensorElements & (minAff2.le_set(aff)) & + (aff.lt_set(minAff2 + extentAff2)); } tensorElements = tensorElements.intersect_params(scop.context()); From ab58bb9aeeb974b25447d3826238e0db13da7747 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Mon, 30 Jul 2018 16:40:50 +0200 Subject: [PATCH 62/85] promotedFootprint: use templated isl types --- tc/core/polyhedral/domain_types.h | 1 + tc/core/polyhedral/memory_promotion.cc | 30 ++++++++++++++------------ tc/core/polyhedral/memory_promotion.h | 8 +++---- tc/external/detail/islpp.h | 5 +++++ 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/tc/core/polyhedral/domain_types.h b/tc/core/polyhedral/domain_types.h index b627e53eb..8c3410672 100644 --- a/tc/core/polyhedral/domain_types.h +++ b/tc/core/polyhedral/domain_types.h @@ -3,6 +3,7 @@ namespace polyhedral { struct Band; struct Prefix; +struct Promoted; struct Reduction; struct ReductionSchedule; struct Statement; diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index 841b9882f..d804d37a2 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -147,20 +147,20 @@ bool TensorReferenceGroup::isReadOnly() const { return result; } -isl::set TensorReferenceGroup::promotedFootprint() const { +isl::Set TensorReferenceGroup::promotedFootprint() const { auto space = scopedAccesses().get_space().range(); auto sizes = approximation.box.get_size(); if (!sizes.get_space().has_equal_tuples(space)) { throw promotion::GroupingError("unexpected dimensionality mismatch"); } - isl::set footprint = isl::set::universe(space); - auto identity = isl::multi_aff::identity(space.map_from_set()); + isl::Set footprint = isl::Set::universe(space); + auto identity = isl::MultiAff::identity(space.map_from_set()); for (size_t i = 0, e = sizes.size(); i < e; ++i) { auto aff = identity.get_aff(i); auto size = sizes.get_val(i); - footprint = - footprint & (isl::aff_set(aff) >= 0) & (isl::aff_set(aff) < size); + footprint = footprint & aff.asPwAff().nonneg_set() & + (size - aff).asPwAff().pos_set(); } return footprint; } @@ -175,14 +175,14 @@ std::vector TensorReferenceGroup::approximationSizes() const { } namespace { -isl::map referenceScopedAccessesImpl( +isl::Map referenceScopedAccessesImpl( const TensorReferenceGroup& group, AccessType type) { if (group.references.size() == 0) { throw promotion::GroupingError("no references in the group"); } - auto accesses = - isl::map::empty(group.references.front()->scopedAccess.get_space()); + auto accesses = isl::Map::empty( + group.references.front()->scopedAccess.get_space()); for (const auto& ref : group.references) { if (ref->type != type) { @@ -203,11 +203,11 @@ isl::set TensorReferenceGroup::readFootprint() const { return referenceScopedAccessesImpl(*this, AccessType::Read).range(); } -isl::map TensorReferenceGroup::scopedWrites() const { +isl::Map TensorReferenceGroup::scopedWrites() const { return referenceScopedAccessesImpl(*this, AccessType::Write); } -isl::map TensorReferenceGroup::scopedReads() const { +isl::Map TensorReferenceGroup::scopedReads() const { return referenceScopedAccessesImpl(*this, AccessType::Read); } @@ -509,7 +509,8 @@ ScheduleTree* insertCopiesUnder( // control flow, but we should only write back elements that are actually // written to. In any case, intersect the footprint with the set of existing // tensor elements. - auto promotedFootprint = group.promotedFootprint().set_tuple_id(groupId); + auto promotedFootprint = + group.promotedFootprint().set_tuple_id(groupId); auto scheduleUniverse = isl::set::universe(promotionSpace.domain().unwrap().domain()); auto arrayId = promotionSpace.domain().unwrap().get_map_range_tuple_id(); @@ -518,9 +519,10 @@ ScheduleTree* insertCopiesUnder( approximatedRead = approximatedRead.product(promotedFootprint); auto readExtension = extension.intersect_range(approximatedRead).set_range_tuple_id(readId); - auto writtenElements = - group.scopedWrites().intersect_range(tensorElements).wrap(); - writtenElements = writtenElements.product(promotedFootprint); + auto writtenElements = group.scopedWrites() + .intersect_range(tensorElements) + .wrap() + .product(promotedFootprint); auto writeExtension = extension.intersect_range(writtenElements).set_range_tuple_id(writeId); diff --git a/tc/core/polyhedral/memory_promotion.h b/tc/core/polyhedral/memory_promotion.h index dd8ec9c89..ddc61c6fb 100644 --- a/tc/core/polyhedral/memory_promotion.h +++ b/tc/core/polyhedral/memory_promotion.h @@ -126,9 +126,9 @@ class TensorReferenceGroup { } // Access relations in terms of partial schedule of the scoping point. - isl::map scopedWrites() const; - isl::map scopedReads() const; - isl::map scopedAccesses() const { + isl::Map scopedWrites() const; + isl::Map scopedReads() const; + isl::Map scopedAccesses() const { return scopedWrites().unite(scopedReads()); } @@ -146,7 +146,7 @@ class TensorReferenceGroup { isl::map approximateScopedAccesses() const; isl::multi_aff promotion() const; - isl::set promotedFootprint() const; + isl::Set promotedFootprint() const; std::vector approximationSizes() const; diff --git a/tc/external/detail/islpp.h b/tc/external/detail/islpp.h index d527c4192..d83714286 100644 --- a/tc/external/detail/islpp.h +++ b/tc/external/detail/islpp.h @@ -45,6 +45,11 @@ inline T operator-(T a, T b) { return a.sub(b); } +template +inline auto operator-(isl::val a, T b) -> decltype(b.add_constant(a)) { + return b.neg().add_constant(a); +} + template inline T operator&(T S1, T S2) { return S1.intersect(S2); From d020eda11d5f226928a5fa5ba012f6a57da9bf53 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Mon, 30 Jul 2018 17:57:03 +0200 Subject: [PATCH 63/85] TensorReferenceGroup::promotion: temporarily remove type deduction This allows outputRanges to be converted to templated isl types without having to convert TensorReferenceGroup::promotion at the same time. Automatic type deduction will be reintroduced when TensorReferenceGroup::promotion is converted. --- tc/core/polyhedral/memory_promotion.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index d804d37a2..f83d882a1 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -379,9 +379,10 @@ isl::multi_aff TensorReferenceGroup::promotion() const { auto originalSpaceInserter = isl::multi_aff::domain_map(accessSpace); // Lower bounds and offsets space is S -> O; transform into [S -> O] -> O. - auto lowerBounds = + isl::multi_aff lowerBounds = approximation.lowerBounds().pullback(originalSpaceInserter); - auto offsets = approximation.strideOffsets.pullback(originalSpaceInserter); + isl::multi_aff offsets = + approximation.strideOffsets.pullback(originalSpaceInserter); // Create promotion starting by identity in [S -> O] -> O. auto original = isl::multi_aff::range_map(accessSpace); From 56e6fcb9510fe20918e317d67fae16245f1dc498 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Mon, 30 Jul 2018 17:57:03 +0200 Subject: [PATCH 64/85] outputRanges: use templated isl types Since removeRangeStrides has not been converted yet, a separate variable is introduced to store its result. Since ScopedFootprint::strideOffsets is modified, TensorReferenceGroup::promotion needs some modifications too. --- tc/core/polyhedral/memory_promotion.cc | 17 ++++++++++------- tc/core/polyhedral/memory_promotion.h | 4 ++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index f83d882a1..b9564618c 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -61,10 +61,12 @@ isl::map removeRangeStrides( // Compute a box approximation of the range of the given relation, // including the lower bounds, the box sizes, and the strides. // If the range has strides, remove them first. -ScopedFootprint outputRanges(isl::map access) { +ScopedFootprint outputRanges(isl::Map access) { ScopedFootprint footprint; - footprint.strideValues = isl::multi_val::zero(access.get_space().range()); - footprint.strideOffsets = isl::multi_aff::zero(access.get_space()); + footprint.strideValues = + isl::MultiVal::zero(access.get_space().range()); + footprint.strideOffsets = + isl::MultiAff::zero(access.get_space()); int nSubscripts = footprint.strideValues.size(); for (int i = 0; i < nSubscripts; ++i) { @@ -74,10 +76,10 @@ ScopedFootprint outputRanges(isl::map access) { footprint.strideOffsets.set_aff(i, si.get_offset()); } - access = removeRangeStrides( + auto accessNoStrides = removeRangeStrides( access, footprint.strideValues, footprint.strideOffsets); - footprint.box = access.get_range_simple_fixed_box_hull(); + footprint.box = accessNoStrides.get_range_simple_fixed_box_hull(); return footprint; } } // namespace @@ -371,12 +373,13 @@ TensorGroups TensorReferenceGroup::accessedWithin( // outer schedule dimensions. isl::multi_aff TensorReferenceGroup::promotion() const { // access space is S -> O - isl::map map = scopedAccesses(); + auto map = scopedAccesses(); auto accessSpace = map.get_space(); // Construct a projection multi-aff in [S -> O] -> S // for further precomposition. - auto originalSpaceInserter = isl::multi_aff::domain_map(accessSpace); + auto originalSpaceInserter = + isl::MultiAff, Prefix>::domain_map(accessSpace); // Lower bounds and offsets space is S -> O; transform into [S -> O] -> O. isl::multi_aff lowerBounds = diff --git a/tc/core/polyhedral/memory_promotion.h b/tc/core/polyhedral/memory_promotion.h index ddc61c6fb..4909c8655 100644 --- a/tc/core/polyhedral/memory_promotion.h +++ b/tc/core/polyhedral/memory_promotion.h @@ -59,8 +59,8 @@ struct ScopedFootprint { } isl::fixed_box box; - isl::multi_val strideValues; - isl::multi_aff strideOffsets; + isl::MultiVal strideValues; + isl::MultiAff strideOffsets; isl::multi_aff lowerBounds() const; }; From 70634b1bb28fd3477a97fbb8f857e3feb2aa0f4b Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Mon, 30 Jul 2018 17:57:03 +0200 Subject: [PATCH 65/85] removeRangeStrides: use templated isl types --- tc/core/polyhedral/memory_promotion.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index b9564618c..7c906369c 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -45,17 +45,19 @@ namespace { // D -> O: o_i = f(D) // // by subtracting "offsets" and by dividing the result by "strides". -isl::map removeRangeStrides( - isl::map relation, - isl::multi_val strides, - isl::multi_aff offsets) { +template +isl::Map removeRangeStrides( + isl::Map relation, + isl::MultiVal strides, + isl::MultiAff offsets) { TC_CHECK_EQ(strides.size(), offsets.size()); auto space = relation.get_space(); - auto stridesMA = isl::multi_aff::identity(space.range().map_from_set()); + auto stridesMA = + isl::MultiAff::identity(space.range().map_from_set()); stridesMA = stridesMA / strides; - return relation.sum(isl::map(offsets.neg())).apply_range(isl::map(stridesMA)); + return relation.sum(offsets.neg().asMap()).apply_range(stridesMA.asMap()); } // Compute a box approximation of the range of the given relation, From 11b8b63e6cee87760e6020f0c39579fecd0baef8 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Mon, 30 Jul 2018 18:09:02 +0200 Subject: [PATCH 66/85] ScopedFootprint.box: use templated isl types --- tc/core/polyhedral/memory_promotion.cc | 2 +- tc/core/polyhedral/memory_promotion.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index 7c906369c..c59b96963 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -136,7 +136,7 @@ isl::map TensorReferenceGroup::approximateScopedAccesses() const { return accessed; } -isl::multi_aff ScopedFootprint::lowerBounds() const { +isl::MultiAff ScopedFootprint::lowerBounds() const { if (dim() == 0) { throw promotion::PromotionNYI("promotion for scalars"); } diff --git a/tc/core/polyhedral/memory_promotion.h b/tc/core/polyhedral/memory_promotion.h index 4909c8655..3cfe2c629 100644 --- a/tc/core/polyhedral/memory_promotion.h +++ b/tc/core/polyhedral/memory_promotion.h @@ -48,21 +48,21 @@ struct ScopedFootprint { isl::val size(size_t pos) const { return box.get_size().get_val(pos); } - isl::aff lowerBound(size_t pos) const { + isl::AffOn lowerBound(size_t pos) const { return box.get_offset().get_aff(pos); } isl::val stride(size_t pos) const { return strideValues.get_val(pos); } - isl::aff strideOffset(size_t pos) const { + isl::AffOn strideOffset(size_t pos) const { return strideOffsets.get_aff(pos); } - isl::fixed_box box; + isl::FixedBox box; isl::MultiVal strideValues; isl::MultiAff strideOffsets; - isl::multi_aff lowerBounds() const; + isl::MultiAff lowerBounds() const; }; // Descriptor of tensor reference in a Scop. From 77ef4972cf239aed99d8732715d724ac98037f9e Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Tue, 31 Jul 2018 09:23:43 +0200 Subject: [PATCH 67/85] TensorReferenceGroup::promotion: use templated isl types --- tc/core/polyhedral/cuda/codegen.cc | 5 +++-- tc/core/polyhedral/memory_promotion.cc | 11 ++++++----- tc/core/polyhedral/memory_promotion.h | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tc/core/polyhedral/cuda/codegen.cc b/tc/core/polyhedral/cuda/codegen.cc index 606cd235c..1aafa3f75 100644 --- a/tc/core/polyhedral/cuda/codegen.cc +++ b/tc/core/polyhedral/cuda/codegen.cc @@ -723,8 +723,9 @@ void emitMappedTensorAccess( // MA = multi_aff, PMA = pw_multi_aff auto access = makeMultiAffAccess(tensorId, subscripts, context); // MA :: D -> O - auto promotion = promotionInfo.group->promotion(); // MA :: [S -> O] -> P - promotion = promotion.set_range_tuple_id(promotionInfo.groupId); + auto prePromotion = promotionInfo.group->promotion(); // MA :: [S -> O] -> P + auto promotion = + prePromotion.set_range_tuple_id(promotionInfo.groupId); auto iteratorMap = context.iteratorMap(); // PMA :: A -> D auto schedule = isl::map::from(promotionInfo.outerSchedule.intersect_domain( context.domain())); // map :: D -> S diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index c59b96963..95b1485ac 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -373,7 +373,8 @@ TensorGroups TensorReferenceGroup::accessedWithin( // elements of the promoted array get assigned different values of the original // array in different outer loop iterations; it's impossible to project out the // outer schedule dimensions. -isl::multi_aff TensorReferenceGroup::promotion() const { +isl::MultiAff, Tensor> +TensorReferenceGroup::promotion() const { // access space is S -> O auto map = scopedAccesses(); auto accessSpace = map.get_space(); @@ -384,13 +385,13 @@ isl::multi_aff TensorReferenceGroup::promotion() const { isl::MultiAff, Prefix>::domain_map(accessSpace); // Lower bounds and offsets space is S -> O; transform into [S -> O] -> O. - isl::multi_aff lowerBounds = + auto lowerBounds = approximation.lowerBounds().pullback(originalSpaceInserter); - isl::multi_aff offsets = - approximation.strideOffsets.pullback(originalSpaceInserter); + auto offsets = approximation.strideOffsets.pullback(originalSpaceInserter); // Create promotion starting by identity in [S -> O] -> O. - auto original = isl::multi_aff::range_map(accessSpace); + auto original = + isl::MultiAff, Tensor>::range_map(accessSpace); auto promotion = (original - offsets) / approximation.strideValues - lowerBounds; diff --git a/tc/core/polyhedral/memory_promotion.h b/tc/core/polyhedral/memory_promotion.h index 3cfe2c629..cbf5890cb 100644 --- a/tc/core/polyhedral/memory_promotion.h +++ b/tc/core/polyhedral/memory_promotion.h @@ -145,7 +145,7 @@ class TensorReferenceGroup { // and relative to the scoping point. isl::map approximateScopedAccesses() const; - isl::multi_aff promotion() const; + isl::MultiAff, Tensor> promotion() const; isl::Set promotedFootprint() const; std::vector approximationSizes() const; From 52b0b73910ba4efc8e2b6fc2af4ad5b851edd50a Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 68/85] use templated isl types in schedule tree --- tc/core/polyhedral/cuda/mapped_scop.cc | 2 +- tc/core/polyhedral/memory_promotion.cc | 14 +++++++--- tc/core/polyhedral/schedule_isl_conversion.cc | 6 ++--- tc/core/polyhedral/schedule_transforms.cc | 19 ++++++++----- tc/core/polyhedral/schedule_transforms.h | 8 +++--- tc/core/polyhedral/schedule_tree.cc | 10 +++---- tc/core/polyhedral/schedule_tree.h | 9 ++++--- tc/core/polyhedral/schedule_tree_elem.cc | 7 ++--- tc/core/polyhedral/schedule_tree_elem.h | 19 +++++++------ tc/core/polyhedral/schedule_utils-inl.h | 27 ++++++++++--------- tc/core/polyhedral/schedule_utils.cc | 17 +++++++----- tc/core/polyhedral/schedule_utils.h | 7 ++--- tc/core/polyhedral/unroll.cc | 10 +++---- tc/external/detail/islpp.h | 8 +++--- 14 files changed, 94 insertions(+), 69 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index 623626369..bcc7a6e44 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -288,7 +288,7 @@ bool MappedScop::detectReductions(ScheduleTree* tree) { // a single reduction for now. // Support for multiple reductions would require a check // that these reductions do not interfere with each other. - auto domain = isl::UnionSet(band->mupa_.domain()); + auto domain = band->mupa_.domain(); auto updates = reductionUpdates(domain, scop()); if (updates.n_set() != 1) { return false; diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index 95b1485ac..252e5781c 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -501,8 +501,10 @@ ScheduleTree* insertCopiesUnder( auto writeSchedule = isl::multi_union_pw_aff(identityCopySchedule.pullback( isl::multi_aff::wrapped_range_map(writeSpace))); - auto readBandNode = ScheduleTree::makeBand(readSchedule); - auto writeBandNode = ScheduleTree::makeBand(writeSchedule); + auto readBandNode = ScheduleTree::makeBand( + isl::MultiUnionPwAff(readSchedule)); + auto writeBandNode = ScheduleTree::makeBand( + isl::MultiUnionPwAff(writeSchedule)); if (unrollAllCopies) { unrollAllMembers(readBandNode->as()); @@ -552,14 +554,18 @@ ScheduleTree* insertCopiesUnder( if (reads) { insertExtensionBefore( - root, tree, tree->child({0}), readExtension, std::move(readFilterNode)); + root, + tree, + tree->child({0}), + isl::UnionMap(readExtension), + std::move(readFilterNode)); } if (writes) { insertExtensionAfter( root, tree, tree->child({0}), - writeExtension, + isl::UnionMap(writeExtension), std::move(writeFilterNode)); } diff --git a/tc/core/polyhedral/schedule_isl_conversion.cc b/tc/core/polyhedral/schedule_isl_conversion.cc index 505dc6acc..28f1fa1de 100644 --- a/tc/core/polyhedral/schedule_isl_conversion.cc +++ b/tc/core/polyhedral/schedule_isl_conversion.cc @@ -243,8 +243,8 @@ std::unique_ptr fromIslScheduleNodeBand( for (size_t i = 0; i < n; ++i) { coincident[i] = b.member_get_coincident(i); } - return ScheduleTreeBand::make( - b.get_partial_schedule(), b.get_permutable(), coincident, unroll); + auto mupa = isl::MultiUnionPwAff(b.get_partial_schedule()); + return ScheduleTreeBand::make(mupa, b.get_permutable(), coincident, unroll); } std::unique_ptr elemFromIslScheduleNode(isl::schedule_node node) { @@ -252,7 +252,7 @@ std::unique_ptr elemFromIslScheduleNode(isl::schedule_node node) { if (auto band = node.as()) { return fromIslScheduleNodeBand(band); } else if (auto context = node.as()) { - auto c = context.get_context(); + auto c = isl::Set(context.get_context()); return ScheduleTreeContext::make(c); } else if (auto domain = node.as()) { auto c = domain.get_domain(); diff --git a/tc/core/polyhedral/schedule_transforms.cc b/tc/core/polyhedral/schedule_transforms.cc index c8f4d6f20..9bdc99f28 100644 --- a/tc/core/polyhedral/schedule_transforms.cc +++ b/tc/core/polyhedral/schedule_transforms.cc @@ -89,7 +89,8 @@ ScheduleTree* joinBandsHelper(ScheduleTree* st, bool& moveChildren) { auto& partialSchedule = eb->mupa_; auto& partialScheduleChild = ebChild->mupa_; - partialSchedule = partialSchedule.flat_range_product(partialScheduleChild); + partialSchedule = + partialSchedule.flat_range_product(partialScheduleChild); eb->coincident_.resize( eb->coincident_.size() + ebChild->coincident_.size(), false); eb->unroll_.insert( @@ -285,7 +286,9 @@ ScheduleTree* insertTopLevelEmptyBand(ScheduleTree* root) { return insertNodeBelow(node, ScheduleTree::makeEmptyBand(root)); } -void updateTopLevelContext(detail::ScheduleTree* root, isl::set context) { +void updateTopLevelContext( + detail::ScheduleTree* root, + isl::Set context) { if (!matchOne(tc::polyhedral::domain(tc::polyhedral::context(any())), root)) { root->appendChild( ScheduleTree::makeContext(context, root->detachChildren())); @@ -394,7 +397,7 @@ void insertExtensionAt( ScheduleTree* relativeRoot, ScheduleTree* seqNode, size_t pos, - isl::union_map extension, + isl::UnionMap extension, ScheduleTreeUPtr&& filterNode) { auto extensionTree = seqNode->ancestor(relativeRoot, 1); auto extensionNode = extensionTree->as(); @@ -413,7 +416,7 @@ void insertExtensionBefore( const ScheduleTree* root, ScheduleTree* relativeRoot, ScheduleTree* tree, - isl::union_map extension, + isl::UnionMap extension, ScheduleTreeUPtr&& filterNode) { size_t pos; auto parent = tree->ancestor(relativeRoot, 1); @@ -442,7 +445,7 @@ void insertExtensionAfter( const ScheduleTree* root, ScheduleTree* relativeRoot, ScheduleTree* tree, - isl::union_map extension, + isl::UnionMap extension, ScheduleTreeUPtr&& filterNode) { size_t pos; auto parent = tree->ancestor(relativeRoot, 1); @@ -504,7 +507,7 @@ namespace { * of band node partial schedules. * Elements of a sequence that end up with an empty filter are removed. */ -void gist(ScheduleTree* tree, isl::union_set context) { +void gist(ScheduleTree* tree, isl::UnionSet context) { if (auto bandElem = tree->as()) { bandElem->mupa_ = bandElem->mupa_.gist(context); } else if (auto filterElem = tree->as()) { @@ -534,7 +537,9 @@ void gist(ScheduleTree* tree, isl::union_set context) { * Create a filter node with the given filter and single child node, * after simplifying the child node in the context of the filter. */ -ScheduleTreeUPtr gistedFilter(isl::union_set filter, ScheduleTreeUPtr child) { +ScheduleTreeUPtr gistedFilter( + isl::UnionSet filter, + ScheduleTreeUPtr child) { gist(child.get(), filter); return ScheduleTree::makeFilter(filter, std::move(child)); } diff --git a/tc/core/polyhedral/schedule_transforms.h b/tc/core/polyhedral/schedule_transforms.h index 6820792b4..4fa1f71d2 100644 --- a/tc/core/polyhedral/schedule_transforms.h +++ b/tc/core/polyhedral/schedule_transforms.h @@ -111,7 +111,9 @@ detail::ScheduleTree* insertTopLevelEmptyBand(detail::ScheduleTree* root); // Update the top-level context node by intersecting it with "context". The // top-level context node must be located directly under the root of the tree. // If there is no such node, insert one first. -void updateTopLevelContext(detail::ScheduleTree* root, isl::set context); +void updateTopLevelContext( + detail::ScheduleTree* root, + isl::Set context); // In a tree starting at "root", insert a sequence node with // as only child the node identified by "tree". @@ -175,7 +177,7 @@ void insertExtensionBefore( const detail::ScheduleTree* root, detail::ScheduleTree* relativeRoot, detail::ScheduleTree* tree, - isl::union_map extension, + isl::UnionMap extension, ScheduleTreeUPtr&& filterNode); // Insert an extension with the given extension map and extension filter node @@ -190,7 +192,7 @@ void insertExtensionAfter( const detail::ScheduleTree* root, detail::ScheduleTree* relativeRoot, detail::ScheduleTree* tree, - isl::union_map extension, + isl::UnionMap extension, ScheduleTreeUPtr&& filterNode); // Given a sequence node in the schedule tree, insert diff --git a/tc/core/polyhedral/schedule_tree.cc b/tc/core/polyhedral/schedule_tree.cc index 1c7779d8f..441da9bdf 100644 --- a/tc/core/polyhedral/schedule_tree.cc +++ b/tc/core/polyhedral/schedule_tree.cc @@ -200,7 +200,7 @@ size_t ScheduleTree::scheduleDepth(const ScheduleTree* relativeRoot) const { } std::unique_ptr ScheduleTree::makeBand( - isl::multi_union_pw_aff mupa, + isl::MultiUnionPwAff mupa, std::vector&& children) { std::vector coincident(mupa.size(), false); std::vector unroll(mupa.size(), false); @@ -212,9 +212,9 @@ std::unique_ptr ScheduleTree::makeBand( ScheduleTreeUPtr ScheduleTree::makeEmptyBand(const ScheduleTree* root) { auto domain = root->as(); TC_CHECK(domain); - auto space = domain->domain_.get_space().set_from_params(); - auto mv = isl::multi_val::zero(space); - auto zero = isl::multi_union_pw_aff(domain->domain_, mv); + auto space = domain->domain_.get_space().add_unnamed_tuple_ui(0); + auto mv = isl::MultiVal::zero(space); + auto zero = isl::MultiUnionPwAff(domain->domain_, mv); return ScheduleTree::makeBand(zero); } @@ -225,7 +225,7 @@ std::unique_ptr ScheduleTree::makeDomain( } std::unique_ptr ScheduleTree::makeContext( - isl::set context, + isl::Set context, std::vector&& children) { return ScheduleTreeContext::make(context, std::move(children)); } diff --git a/tc/core/polyhedral/schedule_tree.h b/tc/core/polyhedral/schedule_tree.h index 403dd0210..bfe82504e 100644 --- a/tc/core/polyhedral/schedule_tree.h +++ b/tc/core/polyhedral/schedule_tree.h @@ -21,6 +21,7 @@ #include #include "tc/core/check.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/mapping_types.h" #include "tc/core/polyhedral/options.h" #include "tc/core/utils/vararg.h" @@ -280,7 +281,7 @@ struct ScheduleTree { // Factory functions // static ScheduleTreeUPtr makeBand( - isl::multi_union_pw_aff mupa, + isl::MultiUnionPwAff mupa, std::vector&& children = {}); // Return a zero-dimensional band for use in a tree with the given root. @@ -291,7 +292,7 @@ struct ScheduleTree { std::vector&& children = {}); static ScheduleTreeUPtr makeContext( - isl::set context, + isl::Set context, std::vector&& children = {}); static ScheduleTreeUPtr makeFilter( @@ -332,7 +333,7 @@ struct ScheduleTree { template static ScheduleTreeUPtr makeBand( - isl::multi_union_pw_aff mupa, + isl::MultiUnionPwAff mupa, Args&&... args) { return makeBand( mupa, vectorFromArgs(std::forward(args)...)); @@ -345,7 +346,7 @@ struct ScheduleTree { } template - static ScheduleTreeUPtr makeContext(isl::set context, Args&&... args) { + static ScheduleTreeUPtr makeContext(isl::Set<> context, Args&&... args) { return makeContext( context, vectorFromArgs(std::forward(args)...)); } diff --git a/tc/core/polyhedral/schedule_tree_elem.cc b/tc/core/polyhedral/schedule_tree_elem.cc index 413458e91..48d4025ae 100644 --- a/tc/core/polyhedral/schedule_tree_elem.cc +++ b/tc/core/polyhedral/schedule_tree_elem.cc @@ -26,6 +26,7 @@ #include "tc/core/check.h" #include "tc/core/constants.h" #include "tc/core/flags.h" +#include "tc/core/polyhedral/domain_types.h" #include "tc/core/polyhedral/schedule_isl_conversion.h" #include "tc/core/polyhedral/schedule_tree.h" #include "tc/core/scope_guard.h" @@ -183,7 +184,7 @@ std::unique_ptr ScheduleTreeSet::make( } std::unique_ptr ScheduleTreeBand::make( - isl::multi_union_pw_aff mupa, + isl::MultiUnionPwAff mupa, bool permutable, std::vector coincident, std::vector unroll, @@ -236,8 +237,8 @@ void ScheduleTreeBand::drop(size_t pos, size_t n) { auto list = mupa_.get_union_pw_aff_list(); auto space = mupa_.get_space().params(); list = list.drop(pos, n); - space = space.add_unnamed_tuple_ui(list.size()); - mupa_ = isl::multi_union_pw_aff(space, list); + auto spaceBand = space.add_unnamed_tuple_ui(list.size()); + mupa_ = isl::MultiUnionPwAff(spaceBand, list); std::copy( coincident_.begin() + pos + n, diff --git a/tc/core/polyhedral/schedule_tree_elem.h b/tc/core/polyhedral/schedule_tree_elem.h index f32cca862..3e1dd42aa 100644 --- a/tc/core/polyhedral/schedule_tree_elem.h +++ b/tc/core/polyhedral/schedule_tree_elem.h @@ -64,7 +64,7 @@ struct ScheduleTreeContext : public ScheduleTree { } public: - isl::set context_; + isl::Set context_; }; struct ScheduleTreeDomain : public ScheduleTree { @@ -100,7 +100,7 @@ struct ScheduleTreeDomain : public ScheduleTree { } public: - isl::union_set domain_; + isl::UnionSet domain_; }; struct ScheduleTreeExtension : public ScheduleTree { @@ -136,7 +136,7 @@ struct ScheduleTreeExtension : public ScheduleTree { } public: - isl::union_map extension_; + isl::UnionMap extension_; }; struct ScheduleTreeFilter : public ScheduleTree { @@ -172,7 +172,7 @@ struct ScheduleTreeFilter : public ScheduleTree { } public: - isl::union_set filter_; + isl::UnionSet filter_; }; struct ScheduleTreeMapping : public ScheduleTree { @@ -216,7 +216,7 @@ struct ScheduleTreeMapping : public ScheduleTree { // Mapping from identifiers to affine functions on domain elements. const Mapping mapping; // Assignment of the affine functions to the identifiers as parameters. - isl::union_set filter_; + isl::UnionSet filter_; }; struct ScheduleTreeSequence : public ScheduleTree { @@ -310,7 +310,7 @@ struct ScheduleTreeBand : public ScheduleTree { // Replace "mupa" by its greatest integer part to ensure that the // schedule is always integral. static std::unique_ptr make( - isl::multi_union_pw_aff mupa, + isl::MultiUnionPwAff mupa, bool permutable, std::vector coincident, std::vector unroll, @@ -336,18 +336,17 @@ struct ScheduleTreeBand : public ScheduleTree { isl::MultiUnionPwAff memberRange(size_t first, size_t n) const { auto list = mupa_.get_union_pw_aff_list(); - auto space = mupa_.get_space().params().add_unnamed_tuple_ui(n); + auto space = mupa_.get_space().params().add_unnamed_tuple_ui(n); auto end = first + n; TC_CHECK_LE(end, nMember()); list = list.drop(end, nMember() - end); list = list.drop(0, first); - return isl::MultiUnionPwAff( - isl::multi_union_pw_aff(space, list)); + return isl::MultiUnionPwAff(space, list); } public: bool permutable_{false}; - isl::multi_union_pw_aff mupa_; + isl::MultiUnionPwAff mupa_; std::vector coincident_; // For each member, should the corresponding loop in the generated code diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index e3e096144..4ef8cb834 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -26,15 +26,16 @@ namespace tc { namespace polyhedral { -inline isl::union_map extendSchedule( +template +isl::UnionMap extendSchedule( const detail::ScheduleTree* node, - isl::union_map schedule) { + isl::UnionMap schedule) { using namespace polyhedral::detail; if (auto bandElem = node->as()) { if (bandElem->nMember() > 0) { - schedule = - schedule.flat_range_product(isl::union_map::from(bandElem->mupa_)); + schedule = schedule.template flat_range_product( + bandElem->mupa_.toUnionMap()); } } else if (auto filterElem = node->as()) { schedule = schedule.intersect_domain(filterElem->filter_); @@ -42,15 +43,18 @@ inline isl::union_map extendSchedule( // FIXME: we may need to restrict the range of reversed extension map to // schedule values that correspond to active domain elements at this // point. - schedule = schedule.unite( - extensionElem->extension_.reverse().intersect_range(schedule.range())); + auto extension = extensionElem->extension_.reverse(); + auto specializedExtension = isl::UnionMap(extension); + schedule = + schedule.unite(specializedExtension.intersect_range(schedule.range())); } return schedule; } namespace detail { -inline isl::union_map partialScheduleImpl( +template +inline isl::UnionMap partialScheduleImpl( const ScheduleTree* root, const ScheduleTree* node, bool useNode) { @@ -61,7 +65,8 @@ inline isl::union_map partialScheduleImpl( TC_CHECK_GT(nodes.size(), 0u) << "root node does not have a prefix schedule"; auto domain = root->as(); TC_CHECK(domain); - auto schedule = isl::union_map::from_domain(domain->domain_); + auto schedule = + isl::UnionMap::from_domain(domain->domain_); for (auto anc : nodes) { if (anc->as()) { TC_CHECK(anc == root); @@ -77,16 +82,14 @@ template inline isl::UnionMap prefixSchedule( const detail::ScheduleTree* root, const detail::ScheduleTree* node) { - auto prefix = detail::partialScheduleImpl(root, node, false); - return isl::UnionMap(prefix); + return detail::partialScheduleImpl(root, node, false); } template inline isl::UnionMap partialSchedule( const detail::ScheduleTree* root, const detail::ScheduleTree* node) { - auto prefix = detail::partialScheduleImpl(root, node, true); - return isl::UnionMap(prefix); + return detail::partialScheduleImpl(root, node, true); } namespace detail { diff --git a/tc/core/polyhedral/schedule_utils.cc b/tc/core/polyhedral/schedule_utils.cc index e6b1745cf..cc8d51889 100644 --- a/tc/core/polyhedral/schedule_utils.cc +++ b/tc/core/polyhedral/schedule_utils.cc @@ -32,7 +32,9 @@ namespace { /* * If "node" is any filter, then intersect "domain" with that filter. */ -isl::union_set applyFilter(isl::union_set domain, const ScheduleTree* node) { +isl::UnionSet applyFilter( + isl::UnionSet domain, + const ScheduleTree* node) { if (auto filterElem = node->as()) { return domain.intersect(filterElem->filter_); } @@ -42,7 +44,9 @@ isl::union_set applyFilter(isl::union_set domain, const ScheduleTree* node) { /* * If "node" is a mapping, then intersect "domain" with its filter. */ -isl::union_set applyMapping(isl::union_set domain, const ScheduleTree* node) { +isl::UnionSet applyMapping( + isl::UnionSet domain, + const ScheduleTree* node) { if (auto filterElem = node->as()) { return domain.intersect(filterElem->filter_); } @@ -55,10 +59,11 @@ isl::union_set applyMapping(isl::union_set domain, const ScheduleTree* node) { // Domain elements are introduced by the root domain node. Some nodes // refine this set of elements based on "filter". Extension nodes // are considered to introduce additional domain points. -isl::union_set collectDomain( +isl::UnionSet collectDomain( const ScheduleTree* root, const vector& nodes, - isl::union_set (*filter)(isl::union_set domain, const ScheduleTree* node)) { + isl::UnionSet ( + *filter)(isl::UnionSet domain, const ScheduleTree* node)) { auto domainElem = root->as(); TC_CHECK(domainElem) << "root must be a Domain node" << *root; @@ -67,7 +72,7 @@ isl::union_set collectDomain( for (auto anc : nodes) { domain = filter(domain, anc); if (auto extensionElem = anc->as()) { - isl::union_map parentSchedule = prefixSchedule(root, anc); + auto parentSchedule = prefixSchedule(root, anc); auto extension = extensionElem->extension_; TC_CHECK(parentSchedule) << "missing root domain node"; parentSchedule = parentSchedule.intersect_domain(domain); @@ -87,7 +92,7 @@ isl::union_set activeDomainPointsHelper( } // namespace -isl::union_set prefixMappingFilter( +isl::UnionSet prefixMappingFilter( const ScheduleTree* root, const ScheduleTree* node) { return collectDomain(root, node->ancestors(root), &applyMapping); diff --git a/tc/core/polyhedral/schedule_utils.h b/tc/core/polyhedral/schedule_utils.h index f09f8c1b6..7a4d9b201 100644 --- a/tc/core/polyhedral/schedule_utils.h +++ b/tc/core/polyhedral/schedule_utils.h @@ -47,9 +47,10 @@ std::vector collectScheduleTreesPath( // Given a schedule defined by the ancestors of the given node, // extend it to a schedule that also covers the node itself. -isl::union_map extendSchedule( +template +isl::UnionMap extendSchedule( const detail::ScheduleTree* node, - isl::union_map schedule); + isl::UnionMap schedule); // Get the partial schedule defined by ancestors of the given node and the node // itself. @@ -113,7 +114,7 @@ isl::UnionSet activeDomainPointsBelow( // Collect the outer block/thread identifier mappings // into a filter on the active domain elements. -isl::union_set prefixMappingFilter( +isl::UnionSet prefixMappingFilter( const detail::ScheduleTree* root, const detail::ScheduleTree* node); diff --git a/tc/core/polyhedral/unroll.cc b/tc/core/polyhedral/unroll.cc index 916253c27..8353699d7 100644 --- a/tc/core/polyhedral/unroll.cc +++ b/tc/core/polyhedral/unroll.cc @@ -100,7 +100,7 @@ isl::val boundInstancesAndMarkUnroll( auto outerMap = prefix; if (i > 0) { list = list.drop(i, 1); - auto outerSpace = space.add_unnamed_tuple_ui(list.size()); + auto outerSpace = space.add_unnamed_tuple_ui(list.size()); auto outer = isl::multi_union_pw_aff(outerSpace, list); outerMap = outerMap.flat_range_product(isl::union_map::from(outer)); } @@ -116,7 +116,7 @@ isl::val boundInstancesAndMarkUnroll( isl::val boundInstancesAndMarkUnroll( detail::ScheduleTree* st, - isl::union_map prefix, + isl::UnionMap prefix, isl::val unrollFactor); /* @@ -134,7 +134,7 @@ isl::val boundInstancesAndMarkUnroll( */ isl::val boundChildrenInstancesAndMarkUnroll( detail::ScheduleTree* st, - isl::union_map prefix, + isl::UnionMap prefix, isl::val unrollFactor) { if (st->children().size() == 0) { return isl::val::one(unrollFactor.get_ctx()); @@ -163,7 +163,7 @@ isl::val boundChildrenInstancesAndMarkUnroll( */ isl::val boundInstancesAndMarkUnroll( detail::ScheduleTree* st, - isl::union_map prefix, + isl::UnionMap prefix, isl::val unrollFactor) { auto bound = boundChildrenInstancesAndMarkUnroll(st, prefix, unrollFactor); @@ -184,7 +184,7 @@ void markUnroll( } auto unrollVal = isl::val(st->ctx_, unroll); - isl::union_map prefix = prefixSchedule(root, st); + auto prefix = prefixSchedule(root, st); prefix = prefix.intersect_domain(prefixMappingFilter(root, st)); boundInstancesAndMarkUnroll(st, prefix, unrollVal); } diff --git a/tc/external/detail/islpp.h b/tc/external/detail/islpp.h index d83714286..114646ff0 100644 --- a/tc/external/detail/islpp.h +++ b/tc/external/detail/islpp.h @@ -279,9 +279,11 @@ inline bool operator!=(const isl::id& id1, const isl::id& id2) { /////////////////////////////////////////////////////////////////////////////// // Given a space and a list of values, this returns the corresponding multi_val. -template -isl::multi_val makeMultiVal(isl::space s, const std::vector& vals) { - isl::multi_val mv = isl::multi_val::zero(s); +template +isl::MultiVal makeMultiVal( + isl::Space s, + const std::vector& vals) { + isl::MultiVal mv = isl::MultiVal::zero(s); TC_CHECK_EQ(vals.size(), static_cast(mv.size())); for (size_t i = 0; i < vals.size(); ++i) { mv = mv.set_val(i, isl::val(s.get_ctx(), vals[i])); From acdf75a5a09ddf1b74ab7c36ec0802aedcfdeb06 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 1 Aug 2018 17:24:26 +0200 Subject: [PATCH 69/85] MappedScop::map: use templated isl types --- tc/core/polyhedral/cuda/mapped_scop.cc | 10 ++++++---- tc/core/polyhedral/cuda/mapped_scop.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index bcc7a6e44..c5001cab3 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -136,7 +136,9 @@ const CudaDim& mappingSize(const MappedScop* mscop) { // Return a pointer to the updated node (below the inserted filter) // for call chaining purposes. template -ScheduleTree* MappedScop::map(ScheduleTree* tree, isl::union_pw_aff_list list) { +ScheduleTree* MappedScop::map( + ScheduleTree* tree, + isl::UnionPwAffListOn list) { size_t nToMap = list.size(); const auto& extent = mappingSize(this).view; TC_CHECK_LE(nToMap, extent.size()) << "dimension overflow"; @@ -146,7 +148,7 @@ ScheduleTree* MappedScop::map(ScheduleTree* tree, isl::union_pw_aff_list list) { auto universe = domain.universe(); std::vector idList; - auto affList = isl::union_pw_aff_list(list.get_ctx(), 0); + auto affList = isl::UnionPwAffListOn(list.get_ctx(), 0); for (size_t i = 0; i < nToMap; ++i) { auto id = MappingTypeId::makeId(i); auto upa = list.get_at(i); @@ -158,8 +160,8 @@ ScheduleTree* MappedScop::map(ScheduleTree* tree, isl::union_pw_aff_list list) { for (size_t i = nToMap; i < extent.size(); ++i) { auto id = MappingTypeId::makeId(i); - affList = affList.add( - isl::union_pw_aff(universe, isl::val::zero(domain.get_ctx()))); + affList = affList.add(isl::UnionPwAffOn( + universe, isl::val::zero(domain.get_ctx()))); idList.emplace_back(id); } diff --git a/tc/core/polyhedral/cuda/mapped_scop.h b/tc/core/polyhedral/cuda/mapped_scop.h index c971b80e9..31058c3a7 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.h +++ b/tc/core/polyhedral/cuda/mapped_scop.h @@ -151,7 +151,7 @@ class MappedScop { template detail::ScheduleTree* map( detail::ScheduleTree* tree, - isl::union_pw_aff_list list); + isl::UnionPwAffListOn list); // Map "band" to block identifiers and then scale // the band members by "tileSizes". void mapToBlocksAndScaleBand( From 71a64d4a768e6b3edaee8e2d971ddc92c9ddc399 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Wed, 1 Aug 2018 17:08:25 +0200 Subject: [PATCH 70/85] makeMapping: use templated isl types --- tc/core/polyhedral/schedule_tree.cc | 5 ++--- tc/core/polyhedral/schedule_tree.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tc/core/polyhedral/schedule_tree.cc b/tc/core/polyhedral/schedule_tree.cc index 441da9bdf..fe5763cb2 100644 --- a/tc/core/polyhedral/schedule_tree.cc +++ b/tc/core/polyhedral/schedule_tree.cc @@ -238,14 +238,13 @@ std::unique_ptr ScheduleTree::makeFilter( std::unique_ptr ScheduleTree::makeMappingUnsafe( const std::vector& mappedIds, - isl::union_pw_aff_list mappedAffs, + isl::UnionPwAffListOn mappedAffs, std::vector&& children) { TC_CHECK_EQ(mappedIds.size(), static_cast(mappedAffs.size())) << "expected as many mapped ids as affs"; ScheduleTreeMapping::Mapping mapping; for (size_t i = 0, n = mappedAffs.size(); i < n; ++i) { - auto aff = isl::UnionPwAffOn(mappedAffs.get_at(i)); - mapping.emplace(mappedIds.at(i), aff); + mapping.emplace(mappedIds.at(i), mappedAffs.get_at(i)); } TC_CHECK_GE(mapping.size(), 1u) << "empty mapping"; TC_CHECK_EQ(mappedIds.size(), mapping.size()) diff --git a/tc/core/polyhedral/schedule_tree.h b/tc/core/polyhedral/schedule_tree.h index bfe82504e..485d2fb65 100644 --- a/tc/core/polyhedral/schedule_tree.h +++ b/tc/core/polyhedral/schedule_tree.h @@ -302,7 +302,7 @@ struct ScheduleTree { template static inline ScheduleTreeUPtr makeMapping( const std::vector& mappedIds, - isl::union_pw_aff_list mappedAffs, + isl::UnionPwAffListOn mappedAffs, std::vector&& children = {}) { static_assert( std::is_base_of::value, @@ -319,7 +319,7 @@ struct ScheduleTree { // Internal type-unsafe function to construct mappings. static ScheduleTreeUPtr makeMappingUnsafe( const std::vector& mappedIds, - isl::union_pw_aff_list mappedAffs, + isl::UnionPwAffListOn mappedAffs, std::vector&& children); public: From 4166522ac023dc44ed8eadd690b18442a5c5d1e9 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Tue, 31 Jul 2018 16:30:37 +0200 Subject: [PATCH 71/85] infixScheduleMupa: use templated isl types --- tc/core/polyhedral/schedule_utils-inl.h | 16 +++++++++------- tc/core/polyhedral/schedule_utils.h | 3 ++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index 4ef8cb834..bd7ca4ec1 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -118,7 +118,8 @@ foldl(const std::vector vec, Func op, T init = T()) { } // namespace detail -inline isl::multi_union_pw_aff infixScheduleMupa( +template +inline isl::MultiUnionPwAff infixScheduleMupa( const detail::ScheduleTree* root, const detail::ScheduleTree* relativeRoot, const detail::ScheduleTree* tree) { @@ -127,13 +128,15 @@ inline isl::multi_union_pw_aff infixScheduleMupa( auto domainElem = root->as(); TC_CHECK(domainElem); auto domain = domainElem->domain_.universe(); - auto zero = isl::multi_val::zero(domain.get_space().set_from_params()); - auto prefix = isl::multi_union_pw_aff(domain, zero); + auto zero = isl::MultiVal::zero( + domain.get_space().add_unnamed_tuple_ui(0)); + auto prefix = isl::MultiUnionPwAff(domain, zero); prefix = foldl( filterType(tree->ancestors(relativeRoot)), - [](const ScheduleTree* st, isl::multi_union_pw_aff pref) { + [](const ScheduleTree* st, + isl::MultiUnionPwAff pref) { auto mupa = st->as()->mupa_; - return pref.flat_range_product(mupa); + return pref.template flat_range_product(mupa); }, prefix); return prefix; @@ -143,8 +146,7 @@ template inline isl::MultiUnionPwAff prefixScheduleMupa( const detail::ScheduleTree* root, const detail::ScheduleTree* tree) { - auto prefix = infixScheduleMupa(root, root, tree); - return isl::MultiUnionPwAff(prefix); + return infixScheduleMupa(root, root, tree); } template diff --git a/tc/core/polyhedral/schedule_utils.h b/tc/core/polyhedral/schedule_utils.h index 7a4d9b201..26ffb04b4 100644 --- a/tc/core/polyhedral/schedule_utils.h +++ b/tc/core/polyhedral/schedule_utils.h @@ -72,7 +72,8 @@ isl::UnionMap prefixSchedule( // function on the universe domain of the schedule tree. // Note that this function does not take into account // any intermediate filter nodes. -isl::multi_union_pw_aff infixScheduleMupa( +template +isl::MultiUnionPwAff infixScheduleMupa( const detail::ScheduleTree* root, const detail::ScheduleTree* relativeRoot, const detail::ScheduleTree* tree); From eddcc7a5ece90179695eb6848588cdca72ff1a99 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 72/85] MappedScop::findBestSync: use templated isl types --- tc/core/polyhedral/cuda/mapped_scop.cc | 6 +++--- tc/core/polyhedral/cuda/mapped_scop.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tc/core/polyhedral/cuda/mapped_scop.cc b/tc/core/polyhedral/cuda/mapped_scop.cc index c5001cab3..e00a947e5 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.cc +++ b/tc/core/polyhedral/cuda/mapped_scop.cc @@ -554,15 +554,15 @@ isl::MultiUnionPwAff MappedScop::blockMappingSchedule( Scop::SyncLevel MappedScop::findBestSync( ScheduleTree* st1, ScheduleTree* st2, - isl::multi_union_pw_aff domainToThread, - isl::multi_union_pw_aff domainToWarp) { + isl::MultiUnionPwAff domainToThread, + isl::MultiUnionPwAff domainToWarp) { // Active points in the two schedule trees auto stRoot = scop_->scheduleRoot(); auto activePoints1 = activeDomainPointsBelow(stRoot, st1); auto activePoints2 = activeDomainPointsBelow(stRoot, st2); // The dependences between the two schedule trees - isl::union_map dependences = scop_->dependences; + auto dependences = scop_->dependences; dependences = dependences.intersect_domain(activePoints1); dependences = dependences.intersect_range(activePoints2); if (dependences.is_empty()) { diff --git a/tc/core/polyhedral/cuda/mapped_scop.h b/tc/core/polyhedral/cuda/mapped_scop.h index 31058c3a7..fc92a2932 100644 --- a/tc/core/polyhedral/cuda/mapped_scop.h +++ b/tc/core/polyhedral/cuda/mapped_scop.h @@ -188,8 +188,8 @@ class MappedScop { Scop::SyncLevel findBestSync( detail::ScheduleTree* st1, detail::ScheduleTree* st2, - isl::multi_union_pw_aff domainToThread, - isl::multi_union_pw_aff domainToWarp); + isl::MultiUnionPwAff domainToThread, + isl::MultiUnionPwAff domainToWarp); public: // Find best configuration of synchronizations in a sequence, minimizing From cff20731fbca9ea5bf18cd14846f2cd68302401a Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 73/85] Scop::domainRef: use templated isl types --- tc/core/polyhedral/scop.cc | 4 ++-- tc/core/polyhedral/scop.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tc/core/polyhedral/scop.cc b/tc/core/polyhedral/scop.cc index 2158a1be0..4046dedd4 100644 --- a/tc/core/polyhedral/scop.cc +++ b/tc/core/polyhedral/scop.cc @@ -85,7 +85,7 @@ ScopUPtr Scop::makeScop( return makeScop(ctx, tc2halide::translate(ctx, treeRef, compilerOptions)); } -isl::union_set& Scop::domainRef() { +isl::UnionSet& Scop::domainRef() { auto dom = scheduleRoot()->as(); TC_CHECK(dom) << "root is not a domain in: " << *scheduleRoot(); // TODO: activate this when the invariant has a chance of working (i.e. we @@ -99,7 +99,7 @@ isl::union_set& Scop::domainRef() { } const isl::UnionSet Scop::domain() const { - return isl::UnionSet(const_cast(this)->domainRef()); + return const_cast(this)->domainRef(); } std::ostream& operator<<(std::ostream& os, const Scop& s) { diff --git a/tc/core/polyhedral/scop.h b/tc/core/polyhedral/scop.h index 20cc58896..6a833644a 100644 --- a/tc/core/polyhedral/scop.h +++ b/tc/core/polyhedral/scop.h @@ -511,7 +511,7 @@ struct Scop { // By analogy with generalized functions, the domain is the "support" part // of the ScheduleTree "function". private: - isl::union_set& domainRef(); + isl::UnionSet& domainRef(); public: const isl::UnionSet domain() const; From dd5e513242fe1d3975bf5f18b1cf6c79b0ac239c Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 74/85] promoteToRegistersBelow: use templated isl types --- tc/core/polyhedral/cuda/memory_promotion_heuristic.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index 375a78c40..13407c944 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -654,8 +654,7 @@ void promoteToRegistersBelow(MappedScop& mscop, detail::ScheduleTree* scope) { auto blockSchedule = mscop.blockMappingSchedule(mscop.schedule()); // Pure affine schedule without (mapping) filters. - isl::multi_union_pw_aff partialSchedMupa = - partialScheduleMupa(root, scope); + auto partialSchedMupa = partialScheduleMupa(root, scope); // Schedule with block mapping filter. auto partialSched = isl::union_map::from(partialSchedMupa).intersect_domain(blockMapping); @@ -663,7 +662,7 @@ void promoteToRegistersBelow(MappedScop& mscop, detail::ScheduleTree* scope) { // performed with respect to the block mapping, so append the block schedule. // If the partial schedule contains it already, it will just end up with // identical dimensions without affecting the result of the checks. - partialSchedMupa = partialSchedMupa.flat_range_product(blockSchedule); + auto partialSchedBlockMupa = partialSchedMupa.range_product(blockSchedule); for (auto& tensorGroups : groupMap) { auto tensorId = tensorGroups.first; @@ -677,11 +676,11 @@ void promoteToRegistersBelow(MappedScop& mscop, detail::ScheduleTree* scope) { continue; } if (!isPromotableToRegistersBelow( - *group, root, scope, partialSchedMupa, threadSchedule)) { + *group, root, scope, partialSchedBlockMupa, threadSchedule)) { continue; } // Check reuse within threads. - auto schedule = partialSchedMupa.flat_range_product(threadSchedule); + auto schedule = partialSchedBlockMupa.range_product(threadSchedule); if (!hasReuseWithin(*group, schedule)) { continue; } From c1a5b05469bacd7388125a40d010e3c4a9d13932 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 75/85] partialScheduleMupa: use templated isl types --- tc/core/polyhedral/schedule_utils-inl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tc/core/polyhedral/schedule_utils-inl.h b/tc/core/polyhedral/schedule_utils-inl.h index bd7ca4ec1..416f0111c 100644 --- a/tc/core/polyhedral/schedule_utils-inl.h +++ b/tc/core/polyhedral/schedule_utils-inl.h @@ -155,10 +155,10 @@ inline isl::MultiUnionPwAff partialScheduleMupa( const detail::ScheduleTree* tree) { using namespace polyhedral::detail; - isl::multi_union_pw_aff prefix = prefixScheduleMupa(root, tree); + auto prefix = prefixScheduleMupa(root, tree); auto band = tree->as(); - auto partial = band ? prefix.flat_range_product(band->mupa_) : prefix; - return isl::MultiUnionPwAff(partial); + return band ? prefix.template flat_range_product(band->mupa_) + : prefix; } /* From b614ec0eae48c93f9a3c370188cc042a48db90cf Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 76/85] activeDomainPointsHelper: use templated isl types --- tc/core/polyhedral/schedule_utils.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tc/core/polyhedral/schedule_utils.cc b/tc/core/polyhedral/schedule_utils.cc index cc8d51889..8e6f26bad 100644 --- a/tc/core/polyhedral/schedule_utils.cc +++ b/tc/core/polyhedral/schedule_utils.cc @@ -84,7 +84,7 @@ isl::UnionSet collectDomain( // Get the set of domain elements that are active below // the given branch of nodes. -isl::union_set activeDomainPointsHelper( +isl::UnionSet activeDomainPointsHelper( const ScheduleTree* root, const vector& nodes) { return collectDomain(root, nodes, &applyFilter); @@ -101,8 +101,7 @@ isl::UnionSet prefixMappingFilter( isl::UnionSet activeDomainPoints( const ScheduleTree* root, const ScheduleTree* node) { - return isl::UnionSet( - activeDomainPointsHelper(root, node->ancestors(root))); + return activeDomainPointsHelper(root, node->ancestors(root)); } isl::UnionSet activeDomainPointsBelow( @@ -110,7 +109,7 @@ isl::UnionSet activeDomainPointsBelow( const ScheduleTree* node) { auto ancestors = node->ancestors(root); ancestors.emplace_back(node); - return isl::UnionSet(activeDomainPointsHelper(root, ancestors)); + return activeDomainPointsHelper(root, ancestors); } vector collectScheduleTreesPath( From b5e79f895912a31f10a27041e7a72899a179532d Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 77/85] accessSubscriptsAreUnrolledLoops: temporarily remove type deduction This allows TensorReferenceGroup.originalAccesses() to be converted to templated isl types without having to convert accessSubscriptsAreUnrolledLoops at the same time. Automatic type deduction will be reintroduced when accessSubscriptsAreUnrolledLoops is converted. --- tc/core/polyhedral/cuda/memory_promotion_heuristic.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index 13407c944..47dbbe7a0 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -341,7 +341,7 @@ bool accessSubscriptsAreUnrolledLoops( unrolledDimsMupa = unrolledDimsMupa.intersect_domain(group.originalAccesses().domain()); - auto accesses = group.originalAccesses(); + isl::union_map accesses = group.originalAccesses(); auto schedule = outerSchedule.flat_range_product(unrolledDimsMupa); accesses = accesses.apply_domain(isl::union_map::from(schedule)); From 40977a6a102bd87e8c089b64f78360cbb4e5cae9 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 78/85] TensorReferenceGroup::originalAccesses use templated isl types --- tc/core/polyhedral/memory_promotion.cc | 10 +++++----- tc/core/polyhedral/memory_promotion.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index 252e5781c..2ff1a5bfc 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -216,13 +216,13 @@ isl::Map TensorReferenceGroup::scopedReads() const { } namespace { -isl::union_map referenceOriginalAccessesImpl( +isl::UnionMap referenceOriginalAccessesImpl( const TensorReferenceGroup& group, AccessType type) { if (group.references.size() == 0) { throw promotion::GroupingError("no references in the group"); } - auto accesses = isl::union_map::empty( + auto accesses = isl::UnionMap::empty( group.references.front()->originalAccess.get_space().params()); for (const auto& ref : group.references) { @@ -230,17 +230,17 @@ isl::union_map referenceOriginalAccessesImpl( continue; } auto current = ref->originalAccess; - accesses = accesses.unite(isl::union_map(current)); + accesses = accesses.unite(current.asUnionMap()); } return accesses; } } // namespace -isl::union_map TensorReferenceGroup::originalWrites() const { +isl::UnionMap TensorReferenceGroup::originalWrites() const { return referenceOriginalAccessesImpl(*this, AccessType::Write); } -isl::union_map TensorReferenceGroup::originalReads() const { +isl::UnionMap TensorReferenceGroup::originalReads() const { return referenceOriginalAccessesImpl(*this, AccessType::Read); } diff --git a/tc/core/polyhedral/memory_promotion.h b/tc/core/polyhedral/memory_promotion.h index cbf5890cb..fd2ee993d 100644 --- a/tc/core/polyhedral/memory_promotion.h +++ b/tc/core/polyhedral/memory_promotion.h @@ -135,9 +135,9 @@ class TensorReferenceGroup { // Access relations in terms of Scop domain elements. // The resulting union relations have different domain spaces but identical // range spaces. - isl::union_map originalWrites() const; - isl::union_map originalReads() const; - isl::union_map originalAccesses() const { + isl::UnionMap originalWrites() const; + isl::UnionMap originalReads() const; + isl::UnionMap originalAccesses() const { return originalWrites().unite(originalReads()); } From 0ee8d4b396fca5c9606410c2e6177221c2509baf Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Fri, 27 Jul 2018 10:58:45 +0200 Subject: [PATCH 79/85] makeNextElementMap: use templated isl types --- tc/core/polyhedral/cuda/memory_promotion_heuristic.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index 47dbbe7a0..920dcdbff 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -154,9 +154,12 @@ bool hasReuseWithin( * Create a map that increments the "dim"-th dimension and keeps all other * dimensions unchanged. */ -isl::map makeNextElementMap(isl::space setSpace, unsigned dim) { +template +isl::Map makeNextElementMap( + isl::Space setSpace, + unsigned dim) { auto mapSpace = setSpace.map_from_set(); - auto identityMA = isl::multi_aff::identity(mapSpace); + auto identityMA = isl::MultiAff::identity(mapSpace); size_t size = identityMA.size(); if (dim < 0 || dim >= size) { @@ -167,7 +170,7 @@ isl::map makeNextElementMap(isl::space setSpace, unsigned dim) { auto aff = identityMA.get_aff(dim); identityMA = identityMA.set_aff(dim, aff + 1); - return isl::map(identityMA); + return identityMA.asMap(); } /* From 006db55816cc1380091af8888145977e9feb51f0 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Fri, 27 Jul 2018 12:16:06 +0200 Subject: [PATCH 80/85] hasReuseWithin: use templated isl types --- tc/core/polyhedral/cuda/memory_promotion_heuristic.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index 920dcdbff..d062f97a5 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -142,11 +142,11 @@ std::vector collectBranchMarkers(T root, T node) { * In other words, check that the mapping from statement instances * to pairs of outer schedule points and group elements is not injective. */ +template bool hasReuseWithin( const TensorReferenceGroup& group, - isl::multi_union_pw_aff outer) { - auto map = isl::union_map::from(outer); - map = map.range_product(group.originalAccesses()); + isl::MultiUnionPwAff outer) { + auto map = outer.toUnionMap().range_product(group.originalAccesses()); return !map.is_injective(); } From 74b0b8fcb53ff8d5a1a831f1890e4a6babf70f5d Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 81/85] isPromotableToRegistersBelow: use templated isl types --- .../polyhedral/cuda/memory_promotion_heuristic.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index d062f97a5..ec2754cdb 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -368,23 +368,24 @@ bool accessSubscriptsAreUnrolledLoops( * thread associated to a given pair of tensor element and outer schedule * iteration. */ +template bool isPromotableToRegistersBelow( const TensorReferenceGroup& group, const detail::ScheduleTree* root, const detail::ScheduleTree* scope, - isl::multi_union_pw_aff outer, - isl::multi_union_pw_aff thread) { + isl::MultiUnionPwAff outer, + isl::MultiUnionPwAff thread) { if (!accessSubscriptsAreUnrolledLoops( - group, root, scope, outer.flat_range_product(thread))) { + group, root, scope, outer.range_product(thread))) { return false; } auto originalAccesses = group.originalAccesses(); - auto map = isl::union_map::from(outer); - map = map.range_product(originalAccesses); - map = map.apply_domain(isl::union_map::from(thread)); + auto outerMap = outer.toUnionMap(); + auto pair = outerMap.range_product(originalAccesses); + auto threadToPair = pair.apply_domain(thread.toUnionMap()); - return map.is_injective(); + return threadToPair.is_injective(); } /* From 821426f529c6ff60420a4e24a1b6ebf117158261 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 21 Jun 2018 12:05:24 +0200 Subject: [PATCH 82/85] accessSubscriptsAreUnrolledLoops: use templated isl types --- .../cuda/memory_promotion_heuristic.cc | 27 ++++++++++--------- tc/core/polyhedral/domain_types.h | 1 + 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index ec2754cdb..e37d8bdc6 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -296,11 +296,12 @@ isl::UnionSet collectMappingsTo(const Scop& scop) { * different references may have different values, but all of them remain * independent of non-unrolled loop iterators. */ +template bool accessSubscriptsAreUnrolledLoops( const TensorReferenceGroup& group, const detail::ScheduleTree* root, const detail::ScheduleTree* scope, - isl::multi_union_pw_aff outerSchedule) { + isl::MultiUnionPwAff outerSchedule) { using namespace detail; auto nodes = ScheduleTree::collect(scope); @@ -315,16 +316,16 @@ bool accessSubscriptsAreUnrolledLoops( for (auto leaf : leaves) { auto ancestors = leaf->ancestors(root); ancestors.push_back(leaf); - isl::union_set subdomain = activeDomainPointsBelow(root, leaf); + auto subdomain = activeDomainPointsBelow(root, leaf); - auto unrolledDims = isl::union_pw_aff_list(leaf->ctx_, 1); + auto unrolledDims = isl::UnionPwAffListOn(leaf->ctx_, 1); for (auto node : ancestors) { - auto band = node->as(); + auto band = node->template as(); if (!band) { continue; } - isl::multi_union_pw_aff schedule = band->mupa_; + auto schedule = band->mupa_; schedule = schedule.intersect_domain(subdomain); for (size_t i = 0, e = band->nMember(); i < e; ++i) { if (!band->unroll_[i]) { @@ -334,9 +335,10 @@ bool accessSubscriptsAreUnrolledLoops( } } - auto space = - subdomain.get_space().add_unnamed_tuple_ui(unrolledDims.size()); - auto unrolledDimsMupa = isl::multi_union_pw_aff(space, unrolledDims); + auto space = subdomain.get_space().template add_unnamed_tuple_ui( + unrolledDims.size()); + auto unrolledDimsMupa = + isl::MultiUnionPwAff(space, unrolledDims); // It is possible that no loops are unrolled, in which case // unrolledDimsMupa is zero-dimensional and needs an explicit domain @@ -344,11 +346,12 @@ bool accessSubscriptsAreUnrolledLoops( unrolledDimsMupa = unrolledDimsMupa.intersect_domain(group.originalAccesses().domain()); - isl::union_map accesses = group.originalAccesses(); - auto schedule = outerSchedule.flat_range_product(unrolledDimsMupa); - accesses = accesses.apply_domain(isl::union_map::from(schedule)); + auto accesses = group.originalAccesses(); + auto schedule = outerSchedule.range_product(unrolledDimsMupa); + auto scheduleMap = schedule.toUnionMap(); + auto scheduledAccesses = accesses.apply_domain(scheduleMap); - if (!accesses.is_single_valued()) { + if (!scheduledAccesses.is_single_valued()) { return false; } } diff --git a/tc/core/polyhedral/domain_types.h b/tc/core/polyhedral/domain_types.h index 8c3410672..95f942d87 100644 --- a/tc/core/polyhedral/domain_types.h +++ b/tc/core/polyhedral/domain_types.h @@ -10,6 +10,7 @@ struct Statement; struct Tag; struct Tensor; struct Thread; +struct Unrolled; struct Warp; } // namespace polyhedral From 595eb21d052015f56da1ea73f2c1ff64b6b420bb Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Fri, 27 Jul 2018 16:38:16 +0200 Subject: [PATCH 83/85] collectMappingsTo: use templated isl types --- tc/core/polyhedral/cuda/memory_promotion_heuristic.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc index e37d8bdc6..2b142763f 100644 --- a/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc +++ b/tc/core/polyhedral/cuda/memory_promotion_heuristic.cc @@ -257,13 +257,13 @@ isl::UnionSet collectMappingsTo(const Scop& scop) { auto mappingFilters = detail::ScheduleTree::collect(root, detail::ScheduleTreeType::Mapping); mappingFilters = functional::Filter(isMappingTo, mappingFilters); - auto mapping = isl::union_set::empty(domain.get_space()); + auto mapping = isl::UnionSet::empty(domain.get_space()); for (auto mf : mappingFilters) { auto filterNode = mf->as(); auto filter = filterNode->filter_.intersect(activeDomainPoints(root, mf)); mapping = mapping.unite(filterNode->filter_); } - return isl::UnionSet(mapping); + return mapping; } /* From 1f2cbf7ce5e3463bd1e28773216a74ebd31d08d2 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Fri, 3 Aug 2018 10:58:33 +0200 Subject: [PATCH 84/85] TensorReferenceGroup::approximateScopedAccesses: use templated isl types --- tc/core/polyhedral/memory_promotion.cc | 17 ++++++++++------- tc/core/polyhedral/memory_promotion.h | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index 2ff1a5bfc..17cd7d4cb 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -114,12 +114,15 @@ std::unique_ptr TensorReferenceGroup::makeSingleton( return group; } -isl::map TensorReferenceGroup::approximateScopedAccesses() const { +isl::Map TensorReferenceGroup::approximateScopedAccesses() + const { auto scopedDomain = scopedAccesses().domain(); auto space = approximation.box.get_space(); - auto accessed = isl::map::universe(space).intersect_domain(scopedDomain); + auto accessed = + isl::Map::universe(space).intersect_domain(scopedDomain); - auto identity = isl::multi_aff::identity(space.range().map_from_set()); + auto identity = + isl::MultiAff::identity(space.range().map_from_set()); for (size_t i = 0; i < approximation.dim(); ++i) { auto offset = approximation.lowerBound(i); auto stride = approximation.stride(i); @@ -128,8 +131,8 @@ isl::map TensorReferenceGroup::approximateScopedAccesses() const { auto rhs = identity.get_aff(i); auto lowerBound = offset * stride + strideOffset; auto upperBound = (offset + size) * stride + strideOffset; - auto partial = - (isl::aff_map(lowerBound) <= rhs) & (isl::aff_map(upperBound) > rhs); + auto partial = lowerBound.asPwAff().lt_map((rhs + 1).asPwAff()) & + upperBound.asPwAff().gt_map(rhs.asPwAff()); accessed = accessed & partial; } @@ -525,9 +528,9 @@ ScheduleTree* insertCopiesUnder( auto arrayId = promotionSpace.domain().unwrap().get_map_range_tuple_id(); auto approximatedRead = group.approximateScopedAccesses().intersect_range(tensorElements).wrap(); - approximatedRead = approximatedRead.product(promotedFootprint); + auto product = approximatedRead.product(promotedFootprint); auto readExtension = - extension.intersect_range(approximatedRead).set_range_tuple_id(readId); + extension.intersect_range(product).set_range_tuple_id(readId); auto writtenElements = group.scopedWrites() .intersect_range(tensorElements) .wrap() diff --git a/tc/core/polyhedral/memory_promotion.h b/tc/core/polyhedral/memory_promotion.h index fd2ee993d..236c391d7 100644 --- a/tc/core/polyhedral/memory_promotion.h +++ b/tc/core/polyhedral/memory_promotion.h @@ -143,7 +143,7 @@ class TensorReferenceGroup { // Rectangular overapproximation of the set of tensor elements accessed below // and relative to the scoping point. - isl::map approximateScopedAccesses() const; + isl::Map approximateScopedAccesses() const; isl::MultiAff, Tensor> promotion() const; isl::Set promotedFootprint() const; From 29581f1cac87409cddf8f3255aacf4d519680d75 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 2 Aug 2018 19:46:20 +0200 Subject: [PATCH 85/85] insertCopiesUnder: use templated isl types --- tc/core/polyhedral/memory_promotion.cc | 46 ++++++++++++++------------ 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/tc/core/polyhedral/memory_promotion.cc b/tc/core/polyhedral/memory_promotion.cc index 17cd7d4cb..84224cd03 100644 --- a/tc/core/polyhedral/memory_promotion.cc +++ b/tc/core/polyhedral/memory_promotion.cc @@ -451,11 +451,12 @@ isl::Set tensorElementsSet(const Scop& scop, isl::id tensorId) { * Note that this function drops the name of the target space of "schedule", * but this space is irrelevant for the caller. */ -isl::multi_aff dropDummyTensorDimensions( - isl::multi_aff schedule, +template +isl::MultiAff dropDummyTensorDimensions( + isl::MultiAff schedule, const Scop::PromotedDecl& decl) { auto list = schedule.get_aff_list(); - auto space = schedule.get_space().domain(); + auto domainSpace = schedule.get_space().domain(); auto n = list.size(); for (int i = n - 1; i >= 0; --i) { @@ -464,8 +465,8 @@ isl::multi_aff dropDummyTensorDimensions( } } - space = space.add_unnamed_tuple_ui(list.size()); - return isl::multi_aff(space, list); + auto space = domainSpace.template add_unnamed_tuple_ui(list.size()); + return isl::MultiAff(space, list); } inline void unrollAllMembers(detail::ScheduleTreeBand* band) { @@ -489,20 +490,25 @@ ScheduleTree* insertCopiesUnder( // Take the set of all tensor elements. auto tensorElements = tensorElementsSet(scop, tensorId); - auto promotion = isl::map(group.promotion()).set_range_tuple_id(groupId); + auto promotion = + group.promotion().asMap().set_range_tuple_id(groupId); auto promotionSpace = promotion.get_space(); - auto identityCopySchedule = - isl::multi_aff::identity(promotionSpace.range().map_from_set()); + auto identityCopySchedule = isl::MultiAff::identity( + promotionSpace.range().map_from_set()); // Only iterate over significant tensor dimensions. auto decl = scop.promotedDecl(groupId); identityCopySchedule = dropDummyTensorDimensions(identityCopySchedule, decl); - auto readSpace = promotionSpace.wrap().set_set_tuple_id(readId); - auto writeSpace = promotionSpace.wrap().set_set_tuple_id(writeId); + auto readSpace = promotionSpace.wrap().set_set_tuple_id(readId); + auto writeSpace = promotionSpace.wrap().set_set_tuple_id(writeId); auto readSchedule = isl::multi_union_pw_aff(identityCopySchedule.pullback( - isl::multi_aff::wrapped_range_map(readSpace))); + isl::MultiAff< + isl::NamedPair, Promoted>, + Promoted>::wrapped_range_map(readSpace))); auto writeSchedule = isl::multi_union_pw_aff(identityCopySchedule.pullback( - isl::multi_aff::wrapped_range_map(writeSpace))); + isl::MultiAff< + isl::NamedPair, Promoted>, + Promoted>::wrapped_range_map(writeSpace))); auto readBandNode = ScheduleTree::makeBand( isl::MultiUnionPwAff(readSchedule)); @@ -524,19 +530,19 @@ ScheduleTree* insertCopiesUnder( auto promotedFootprint = group.promotedFootprint().set_tuple_id(groupId); auto scheduleUniverse = - isl::set::universe(promotionSpace.domain().unwrap().domain()); + isl::Set::universe(promotionSpace.domain().unwrap().domain()); auto arrayId = promotionSpace.domain().unwrap().get_map_range_tuple_id(); auto approximatedRead = group.approximateScopedAccesses().intersect_range(tensorElements).wrap(); auto product = approximatedRead.product(promotedFootprint); auto readExtension = - extension.intersect_range(product).set_range_tuple_id(readId); + extension.intersect_range(product).set_range_tuple_id(readId); auto writtenElements = group.scopedWrites() .intersect_range(tensorElements) .wrap() .product(promotedFootprint); - auto writeExtension = - extension.intersect_range(writtenElements).set_range_tuple_id(writeId); + auto writeExtension = extension.intersect_range(writtenElements) + .set_range_tuple_id(writeId); auto readFilterNode = ScheduleTree::makeFilter( isl::set::universe(readExtension.get_space().range()), @@ -557,18 +563,14 @@ ScheduleTree* insertCopiesUnder( if (reads) { insertExtensionBefore( - root, - tree, - tree->child({0}), - isl::UnionMap(readExtension), - std::move(readFilterNode)); + root, tree, tree->child({0}), readExtension, std::move(readFilterNode)); } if (writes) { insertExtensionAfter( root, tree, tree->child({0}), - isl::UnionMap(writeExtension), + writeExtension, std::move(writeFilterNode)); }