[PATCH 1/7] Method::print_arg_list: extract out Method::on_arg_list

1 view
Skip to first unread message

skim...@kotnet.org

unread,
Sep 20, 2021, 3:05:53 PM9/20/21
to isl-dev...@googlegroups.com
From: Sven Verdoolaege <sv...@cerebras.net>

This is a first step towards extracting
a generic Method::on_cpp_arg_list.

Signed-off-by: Sven Verdoolaege <sv...@cerebras.net>
---
interface/cpp.cc | 41 +++++++++++++++++++++++++++++++++--------
interface/cpp.h | 19 +++++++++++++++++++
2 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/interface/cpp.cc b/interface/cpp.cc
index ef66c2b56e..1137c9ad5b 100644
--- a/interface/cpp.cc
+++ b/interface/cpp.cc
@@ -928,6 +928,17 @@ bool cpp_generator::is_implicit_conversion(const Method &cons)
return false;
}

+/* Construct a list combiner for printing a list.
+ */
+Method::list_combiner Method::print_combiner(std::ostream &os)
+{
+ return {
+ [&] () { os << "("; },
+ [&] () { os << ", "; },
+ [&] () { os << ")"; }
+ };
+}
+
/* Get kind of "method" in "clazz".
*
* Given the declaration of a static or member method, returns its kind.
@@ -1005,6 +1016,25 @@ int Method::num_params() const
return c_num_params();
}

+/* Call "on_arg_skip_next" on the arguments from "start" (inclusive)
+ * to "end" (exclusive), calling the methods of "combiner"
+ * before, between and after the arguments.
+ * If "on_arg_skip_next" returns true then the next argument is skipped.
+ */
+void Method::on_arg_list(int start, int end,
+ const Method::list_combiner &combiner,
+ const std::function<bool(int i)> &on_arg_skip_next)
+{
+ combiner.before();
+ for (int i = start; i < end; ++i) {
+ if (i != start)
+ combiner.between();
+ if (on_arg_skip_next(i))
+ ++i;
+ }
+ combiner.after();
+}
+
/* Print the arguments from "start" (inclusive) to "end" (exclusive)
* as arguments to a method of C function call, using "print_arg_skip_next"
* to print each individual argument. If this callback return true
@@ -1013,14 +1043,9 @@ int Method::num_params() const
void Method::print_arg_list(std::ostream &os, int start, int end,
const std::function<bool(int i)> &print_arg_skip_next)
{
- os << "(";
- for (int i = start; i < end; ++i) {
- if (i != start)
- os << ", ";
- if (print_arg_skip_next(i))
- ++i;
- }
- os << ")";
+ on_arg_list(start, end, print_combiner(os), [&] (int i) {
+ return print_arg_skip_next(i);
+ });
}

/* Print the arguments from "start" (inclusive) to "end" (exclusive)
diff --git a/interface/cpp.h b/interface/cpp.h
index f7508b1b39..22ebd3d471 100644
--- a/interface/cpp.h
+++ b/interface/cpp.h
@@ -23,6 +23,9 @@ struct Method {
constructor,
};

+ struct list_combiner;
+ static list_combiner print_combiner(std::ostream &os);
+
Method(const isl_class &clazz, FunctionDecl *fd,
const std::string &name);
Method(const isl_class &clazz, FunctionDecl *fd);
@@ -33,6 +36,9 @@ struct Method {
virtual clang::ParmVarDecl *get_param(int pos) const;
virtual void print_param_use(ostream &os, int pos) const;
bool is_subclass_mutator() const;
+ static void on_arg_list(int start, int end,
+ const list_combiner &combiner,
+ const std::function<bool(int i)> &on_arg_skip_next);
static void print_arg_list(std::ostream &os, int start, int end,
const std::function<bool(int i)> &print_arg_skip_next);
void print_fd_arg_list(std::ostream &os, int start, int end,
@@ -47,6 +53,19 @@ struct Method {
const std::vector<ParmVarDecl *> callbacks;
};

+/* A data structure expressing how Method::on_arg_list should combine
+ * the arguments.
+ *
+ * In particular, "before" is called before any argument is handled;
+ * "between" is called between two arguments and
+ * "after" is called after all arguments have been handled.
+ */
+struct Method::list_combiner {
+ const std::function<void()> before;
+ const std::function<void()> between;
+ const std::function<void()> after;
+};
+
/* A method that does not require its isl type parameters to be a copy.
*/
struct NoCopyMethod : Method {
--
2.25.1

skim...@kotnet.org

unread,
Sep 20, 2021, 3:05:55 PM9/20/21
to isl-dev...@googlegroups.com
From: Sven Verdoolaege <sv...@cerebras.net>

This prepares for extracting out a generic Method::on_cpp_arg_list
in the next commit.

Signed-off-by: Sven Verdoolaege <sv...@cerebras.net>
---
interface/cpp.cc | 32 +++++++++++++++++++++++---------
interface/cpp.h | 3 +++
2 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/interface/cpp.cc b/interface/cpp.cc
index 1137c9ad5b..f009e7f907 100644
--- a/interface/cpp.cc
+++ b/interface/cpp.cc
@@ -1048,15 +1048,14 @@ void Method::print_arg_list(std::ostream &os, int start, int end,
});
}

-/* Print the arguments from "start" (inclusive) to "end" (exclusive)
- * as arguments to a method of C function call, using "print_arg"
- * to print each individual argument.
- * The first argument to this callback is the position of the argument
+/* Call "on_arg" on the arguments from "start" (inclusive) to "end" (exclusive),
+ * calling the methods of "combiner" before, between and after the arguments.
+ * The first argument to "on_arg" is the position of the argument
* in this->fd.
* The second argument is the (first) position in the list of arguments
* with all callback arguments spliced in.
*
- * Call print_arg_list to do the actual printing, skipping
+ * Call on_arg_list to do the actual iteration over the arguments, skipping
* the user argument that comes after every callback argument.
* On the C++ side no user pointer is needed, as arguments can be forwarded
* as part of the std::function argument which specifies the callback function.
@@ -1071,15 +1070,16 @@ void Method::print_arg_list(std::ostream &os, int start, int end,
* while the arguments (excluding the final user pointer)
* take the following positions.
*/
-void Method::print_fd_arg_list(std::ostream &os, int start, int end,
- const std::function<void(int i, int arg)> &print_arg) const
+void Method::on_fd_arg_list(int start, int end,
+ const Method::list_combiner &combiner,
+ const std::function<void(int i, int arg)> &on_arg) const
{
int arg = start;

- print_arg_list(os, start, end, [this, &print_arg, &arg] (int i) {
+ on_arg_list(start, end, combiner, [this, &on_arg, &arg] (int i) {
auto type = fd->getParamDecl(i)->getType();

- print_arg(i, arg++);
+ on_arg(i, arg++);
if (!generator::is_callback(type))
return false;
arg += generator::prototype_n_args(type) - 1;
@@ -1087,6 +1087,20 @@ void Method::print_fd_arg_list(std::ostream &os, int start, int end,
});
}

+/* Print the arguments from "start" (inclusive) to "end" (exclusive)
+ * as arguments to a method of C function call, using "print_arg"
+ * to print each individual argument.
+ * The first argument to this callback is the position of the argument
+ * in this->fd.
+ * The second argument is the (first) position in the list of arguments
+ * with all callback arguments spliced in.
+ */
+void Method::print_fd_arg_list(std::ostream &os, int start, int end,
+ const std::function<void(int i, int arg)> &print_arg) const
+{
+ on_fd_arg_list(start, end, print_combiner(os), print_arg);
+}
+
/* Print the arguments to the method call, using "print_arg"
* to print each individual argument.
* The first argument to this callback is the position of the argument
diff --git a/interface/cpp.h b/interface/cpp.h
index 22ebd3d471..e79407f2b5 100644
--- a/interface/cpp.h
+++ b/interface/cpp.h
@@ -41,6 +41,9 @@ struct Method {
const std::function<bool(int i)> &on_arg_skip_next);
static void print_arg_list(std::ostream &os, int start, int end,
const std::function<bool(int i)> &print_arg_skip_next);
+ void on_fd_arg_list(int start, int end,
+ const list_combiner &combiner,
+ const std::function<void(int i, int arg)> &on_arg) const;
void print_fd_arg_list(std::ostream &os, int start, int end,
const std::function<void(int i, int arg)> &print_arg) const;
void print_cpp_arg_list(std::ostream &os,
--
2.25.1

skim...@kotnet.org

unread,
Sep 20, 2021, 3:05:55 PM9/20/21
to isl-dev...@googlegroups.com
From: Sven Verdoolaege <sv...@cerebras.net>

The correspondence between C function arguments and
tuple kinds is not entirely obvious.
Currently, this correspondence is only needed while printing
the arguments. However, an upcoming commit will need
to iterate over the C function arguments and the corresponding
tuple kinds before the printing.

Extract out a generic Method::on_cpp_arg_list that can
be used both for printing and for this other iteration
over the arguments.

Signed-off-by: Sven Verdoolaege <sv...@cerebras.net>
---
interface/cpp.cc | 17 +++++++++++++++--
interface/cpp.h | 2 ++
2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/interface/cpp.cc b/interface/cpp.cc
index f009e7f907..37c9ef7781 100644
--- a/interface/cpp.cc
+++ b/interface/cpp.cc
@@ -1101,6 +1101,20 @@ void Method::print_fd_arg_list(std::ostream &os, int start, int end,
on_fd_arg_list(start, end, print_combiner(os), print_arg);
}

+/* Call "on_arg" on the arguments to the method call,
+ * calling the methods of "combiner" before, between and after the arguments.
+ * The first argument to "on_arg" is the position of the argument
+ * in this->fd.
+ * The second argument is the (first) position in the list of arguments
+ * with all callback arguments spliced in.
+ */
+void Method::on_cpp_arg_list(const Method::list_combiner &combiner,
+ const std::function<void(int i, int arg)> &on_arg) const
+{
+ int first_param = kind == member_method ? 1 : 0;
+ on_fd_arg_list(first_param, num_params(), combiner, on_arg);
+}
+
/* Print the arguments to the method call, using "print_arg"
* to print each individual argument.
* The first argument to this callback is the position of the argument
@@ -1111,8 +1125,7 @@ void Method::print_fd_arg_list(std::ostream &os, int start, int end,
void Method::print_cpp_arg_list(std::ostream &os,
const std::function<void(int i, int arg)> &print_arg) const
{
- int first_param = kind == member_method ? 1 : 0;
- print_fd_arg_list(os, first_param, num_params(), print_arg);
+ on_cpp_arg_list(print_combiner(os), print_arg);
}

/* Should the parameter at position "pos" be a copy (rather than
diff --git a/interface/cpp.h b/interface/cpp.h
index e79407f2b5..729d02042c 100644
--- a/interface/cpp.h
+++ b/interface/cpp.h
@@ -46,6 +46,8 @@ struct Method {
const std::function<void(int i, int arg)> &on_arg) const;
void print_fd_arg_list(std::ostream &os, int start, int end,
const std::function<void(int i, int arg)> &print_arg) const;
+ void on_cpp_arg_list(const list_combiner &combiner,
+ const std::function<void(int i, int arg)> &on_arg) const;
void print_cpp_arg_list(std::ostream &os,
const std::function<void(int i, int arg)> &print_arg) const;

--
2.25.1

skim...@kotnet.org

unread,
Sep 20, 2021, 3:05:56 PM9/20/21
to isl-dev...@googlegroups.com
From: Sven Verdoolaege <sv...@cerebras.net>

This is more convenient to use than the generic variant,
which takes an extra list_combiner argument.

Signed-off-by: Sven Verdoolaege <sv...@cerebras.net>
---
interface/cpp.cc | 19 +++++++++++++++++++
interface/cpp.h | 3 +++
2 files changed, 22 insertions(+)

diff --git a/interface/cpp.cc b/interface/cpp.cc
index 37c9ef7781..d5c08ebf25 100644
--- a/interface/cpp.cc
+++ b/interface/cpp.cc
@@ -939,6 +939,13 @@ Method::list_combiner Method::print_combiner(std::ostream &os)
};
}

+/* Construct a list combiner for simply iterating over a list.
+ */
+Method::list_combiner Method::empty_combiner()
+{
+ return { [&] () { }, [&] () { }, [&] () { } };
+}
+
/* Get kind of "method" in "clazz".
*
* Given the declaration of a static or member method, returns its kind.
@@ -1115,6 +1122,18 @@ void Method::on_cpp_arg_list(const Method::list_combiner &combiner,
on_fd_arg_list(first_param, num_params(), combiner, on_arg);
}

+/* Call "on_arg" on the arguments to the method call.
+ * The first argument to "on_arg" is the position of the argument
+ * in this->fd.
+ * The second argument is the (first) position in the list of arguments
+ * with all callback arguments spliced in.
+ */
+void Method::on_cpp_arg_list(
+ const std::function<void(int i, int arg)> &on_arg) const
+{
+ on_cpp_arg_list(empty_combiner(), on_arg);
+}
+
/* Print the arguments to the method call, using "print_arg"
* to print each individual argument.
* The first argument to this callback is the position of the argument
diff --git a/interface/cpp.h b/interface/cpp.h
index 729d02042c..55a8fb42ee 100644
--- a/interface/cpp.h
+++ b/interface/cpp.h
@@ -25,6 +25,7 @@ struct Method {

struct list_combiner;
static list_combiner print_combiner(std::ostream &os);
+ static list_combiner empty_combiner();

Method(const isl_class &clazz, FunctionDecl *fd,
const std::string &name);
@@ -48,6 +49,8 @@ struct Method {
const std::function<void(int i, int arg)> &print_arg) const;
void on_cpp_arg_list(const list_combiner &combiner,
const std::function<void(int i, int arg)> &on_arg) const;
+ void on_cpp_arg_list(

skim...@kotnet.org

unread,
Sep 20, 2021, 3:05:57 PM9/20/21
to isl-dev...@googlegroups.com
From: Sven Verdoolaege <sv...@cerebras.net>

This will be reused in the next commit.

Signed-off-by: Sven Verdoolaege <sv...@cerebras.net>
---
interface/template_cpp.cc | 30 +++++++++++++++++++++---------
interface/template_cpp.h | 2 +-
2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/interface/template_cpp.cc b/interface/template_cpp.cc
index 10450c516a..635116c8a9 100644
--- a/interface/template_cpp.cc
+++ b/interface/template_cpp.cc
@@ -1041,22 +1041,34 @@ static std::vector<Kind> add_name(const std::vector<Kind> &tuples)
return named;
}

-/* Add a template class called "name", of which the methods are described
- * by "clazz" and where the corresponding base type has kinds "base_kinds".
+/* Look up the (initial) specializations of the class called "name".
+ * If no specializations have been defined, then return an empty vector.
*
+ * Start from the initial specializations of the corresponding base type.
* If this template class is a multi-expression, then it was derived
* from an anonymous function type. Replace the final Anonymous
* tuple kind by a placeholder in this case.
*/
+static std::vector<Kind> lookup_class_tuples(const std::string &name)
+{
+ std::string base = base_type(name);
+
+ if (base_kinds.count(base) == 0)
+ return { };
+ if (name.find("multi_") != std::string::npos)
+ return add_name(base_kinds.at(base));
+ return base_kinds.at(base);
+}
+
+/* Add a template class called "name", of which the methods are described
+ * by "clazz" and the initial specializations by "class_tuples".
+ */
void template_cpp_generator::add_template_class(const isl_class &clazz,
- const std::string &name, const std::vector<Kind> &base_kinds)
+ const std::string &name, const std::vector<Kind> &class_tuples)
{
auto isl_namespace = cpp_type_printer().isl_namespace();
auto super = isl_namespace + name;
- auto class_tuples = base_kinds;

- if (name.find("multi_") != std::string::npos)
- class_tuples = add_name(class_tuples);
template_classes.emplace(name,
template_class{name, super, clazz, class_tuples});
}
@@ -1082,11 +1094,11 @@ template_cpp_generator::template_cpp_generator(clang::SourceManager &SM,
for (const auto &kvp : classes) {
const auto &clazz = kvp.second;
std::string name = type2cpp(clazz);
- std::string base = base_type(name);
+ const auto &class_tuples = lookup_class_tuples(name);

- if (base_kinds.count(base) == 0)
+ if (class_tuples.empty())
continue;
- add_template_class(clazz, name, base_kinds.at(base));
+ add_template_class(clazz, name, class_tuples);
}
}

diff --git a/interface/template_cpp.h b/interface/template_cpp.h
index a141a4826c..ae3315d812 100644
--- a/interface/template_cpp.h
+++ b/interface/template_cpp.h
@@ -99,7 +99,7 @@ class template_cpp_generator : public cpp_generator {
struct class_impl_printer;

void add_template_class(const isl_class &clazz, const std::string &name,
- const std::vector<Kind> &base_kinds);
+ const std::vector<Kind> &class_tuples);
public:
template_cpp_generator(clang::SourceManager &SM,
std::set<clang::RecordDecl *> &exported_types,
--
2.25.1

skim...@kotnet.org

unread,
Sep 20, 2021, 3:05:58 PM9/20/21
to isl-dev...@googlegroups.com
From: Sven Verdoolaege <sv...@cerebras.net>

If an argument is an anonymous function, then no template argument
needs to be introduced for its final tuple since this is always
Anonymous.

This is especially useful if the argument having an Anonymous final tuple
implies that the result also has an Anonymous final tuple
because the generator refuses to introduce methods
that return a type that should be an anonymous function
but that has a template argument final tuple instead.
This means that a specialized signature would need
to be specified that ensures the return type has a final Anonymous tuple.
In particular, to be able to export the function
isl_set_pw_aff_on_domain_val introduced in the next commit, a specialized

{ { Domain, Anonymous }, { { Domain }, { Anonymous } } }

signature would need to be provided, while this commit ensures
that the current

{ { Domain, Range }, { { Domain }, { Range } } }

works for isl_set_pw_aff_on_domain_val as well.

Signed-off-by: Sven Verdoolaege <sv...@cerebras.net>
---
interface/template_cpp.cc | 76 +++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)

diff --git a/interface/template_cpp.cc b/interface/template_cpp.cc
index 635116c8a9..f80338ac58 100644
--- a/interface/template_cpp.cc
+++ b/interface/template_cpp.cc
@@ -2339,6 +2339,79 @@ void template_cpp_generator::class_printer::add_specialization(
instance.template_class.add_specialization(maybe_unified.second);
}

+/* Does the type of the parameter at position "i" of "method" necessarily
+ * have a final Anonymous tuple?
+ *
+ * If the parameter is not of an isl type or if no specializations
+ * have been defined for the type, then it can be considered anonymous.
+ * Otherwise, if any specialization represents an anonymous function,
+ * then every specialization does, so simply check
+ * the first specialization.
+ */
+static bool param_is_anon(const Method &method, int i)
+{
+ ParmVarDecl *param = method.get_param(i);
+ QualType type = param->getOriginalType();
+
+ if (cpp_generator::is_isl_type(type)) {
+ const auto &name = type->getPointeeType().getAsString();
+ const auto &cpp = cpp_generator::type2cpp(name);
+ const auto &tuples = lookup_class_tuples(cpp);
+
+ if (tuples.empty())
+ return true;
+ return tuples[0].is_anon();
+ }
+
+ return true;
+}
+
+/* Replace the final tuple of "arg_kind" by Anonymous in "sig" and
+ * return the update signature,
+ * unless this would affect the class instance "instance_kind".
+ *
+ * If the original "instance_kind" is a special case
+ * of the result of the substitution, then "instance_kind"
+ * is not affected and the substitution can be applied
+ * to the entire signature.
+ */
+static Signature specialize_anonymous_arg(const Signature &sig,
+ const Kind &arg_kind, const Kind &instance_kind)
+{
+ const auto &subs = compute_unifier(arg_kind.back(), Anonymous);
+ const auto &specialized_instance = instance_kind.apply(subs);
+
+ if (!specializer(specialized_instance, instance_kind).first)
+ return sig;
+
+ return sig.apply(subs);
+}
+
+/* If any of the arguments of "method" is of a type that necessarily
+ * has a final Anonymous tuple, but the corresponding entry
+ * in the signature "sig" is not Anonymous, then replace
+ * that entry by Anonymous and return the updated signature,
+ * unless this would affect the class instance "instance_kind".
+ */
+static Signature specialize_anonymous_args(const Signature &sig,
+ const Method &method, const Kind &instance_kind)
+{
+ auto specialized_sig = sig;
+
+ method.on_cpp_arg_list([&] (int i, int arg) {
+ const auto &arg_kind = sig.args[arg];
+
+ if (arg_kind.is_anon())
+ return;
+ if (!param_is_anon(method, i))
+ return;
+ specialized_sig = specialize_anonymous_arg(specialized_sig,
+ arg_kind, instance_kind);
+ });
+
+ return specialized_sig;
+}
+
/* Print a declaration or definition of the method "method"
* if the template class specialization matches "match_arg".
* Return true if so.
@@ -2351,6 +2424,7 @@ void template_cpp_generator::class_printer::add_specialization(
* If the template class specialization is a special case of
* (the renamed) "match_arg"
* then apply the specializer to the complete (renamed) signature,
+ * specialize any anonymous arguments,
* check that the return kind is allowed and, if so,
* print the declaration or definition using the specialized signature.
*
@@ -2367,6 +2441,8 @@ bool template_cpp_generator::class_printer::print_matching_method(
if (maybe_specializer.first) {
const auto &specializer = maybe_specializer.second;
auto specialized_sig = sig.apply(rename).apply(specializer);
+ specialized_sig = specialize_anonymous_args(specialized_sig,
+ method, instance.kind);
if (!is_return_kind(method, specialized_sig.ret))
return false;

--
2.25.1

skim...@kotnet.org

unread,
Sep 20, 2021, 3:05:59 PM9/20/21
to isl-dev...@googlegroups.com
From: Sven Verdoolaege <sv...@cerebras.net>

In the bindings, it can be more convenient to use a method
on the domain of the object than
to call a named constructor with the domain as argument.

The naming is analogous to isl_set_pw_multi_aff_on_domain_multi_val.

Signed-off-by: Sven Verdoolaege <sv...@cerebras.net>
---
doc/user.pod | 12 +++++++++---
include/isl/aff.h | 3 +++
isl_aff.c | 9 +++++++++
3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/doc/user.pod b/doc/user.pod
index 3c9e7ea727..02f081c995 100644
--- a/doc/user.pod
+++ b/doc/user.pod
@@ -3774,6 +3774,9 @@ then create a piecewise expression over a given domain.
__isl_give isl_pw_aff *isl_pw_aff_val_on_domain(
__isl_take isl_set *domain,
__isl_take isl_val *v);
+ __isl_give isl_pw_aff *isl_set_pw_aff_on_domain_val(
+ __isl_take isl_set *domain,
+ __isl_take isl_val *v);
__isl_give isl_pw_multi_aff *
isl_pw_multi_aff_multi_val_on_domain(
__isl_take isl_set *domain,
@@ -3789,9 +3792,12 @@ then create a piecewise expression over a given domain.
__isl_take isl_set *domain,
__isl_take isl_id *id);

-C<isl_set_pw_multi_aff_on_domain_multi_val> is an alternative name
-for C<isl_pw_multi_aff_multi_val_on_domain>.
-Similarly for C<isl_set_param_pw_aff_on_domain_id> and
+C<isl_set_pw_aff_on_domain_val> is an alternative name
+for C<isl_pw_aff_val_on_domain>.
+Similarly for the pair
+C<isl_set_pw_multi_aff_on_domain_multi_val> and
+C<isl_pw_multi_aff_multi_val_on_domain> and
+for the pair C<isl_set_param_pw_aff_on_domain_id> and
C<isl_pw_aff_param_on_domain_id>.

As a convenience, a piecewise multiple expression can
diff --git a/include/isl/aff.h b/include/isl/aff.h
index 8b0702fcdb..9820a91c97 100644
--- a/include/isl/aff.h
+++ b/include/isl/aff.h
@@ -230,6 +230,9 @@ __isl_give isl_pw_aff *isl_pw_aff_nan_on_domain(__isl_take isl_local_space *ls);
__isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain,
__isl_take isl_val *v);
__isl_overload
+__isl_give isl_pw_aff *isl_set_pw_aff_on_domain_val(__isl_take isl_set *domain,
+ __isl_take isl_val *v);
+__isl_overload
__isl_give isl_pw_aff *isl_pw_aff_param_on_domain_id(
__isl_take isl_set *domain, __isl_take isl_id *id);
__isl_overload
diff --git a/isl_aff.c b/isl_aff.c
index b3f45a2275..75a10ba255 100644
--- a/isl_aff.c
+++ b/isl_aff.c
@@ -7612,6 +7612,15 @@ __isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain,
return isl_pw_aff_alloc(domain, aff);
}

+/* This function performs the same operation as isl_pw_aff_val_on_domain,
+ * but is considered as a function on an isl_set when exported.
+ */
+__isl_give isl_pw_aff *isl_set_pw_aff_on_domain_val(__isl_take isl_set *domain,
+ __isl_take isl_val *v)
+{
+ return isl_pw_aff_val_on_domain(domain, v);
+}
+
/* Return a piecewise affine expression that is equal to the parameter
* with identifier "id" on "domain".
*/
--
2.25.1

Reply all
Reply to author
Forward
0 new messages