-
Notifications
You must be signed in to change notification settings - Fork 139
Open
Description
Hi, i tried to compile the following code using cgeist (commit 77c04bb):
template <typename T, auto N>
auto array_test_template(const std::array<T,N>& array)
{
auto result = std::array<T,N>{};
for (int i=0; i<N; i++) {
result[i] = array[i] + 1;
}
return result;
}
template auto array_test_template<int,4>(const std::array<int,4>&);
template <typename T>
auto vector_test_template(const std::vector<T>& array)
{
auto result = std::vector<T>{};
auto N = array.size();
result.resize(N);
for (int i=0; i<N; i++) {
result[i] = array[i] + 1;
}
return result;
}
template auto vector_test_template<int>(const std::vector<int>&);
Both errored when using cgeist but ok when using clang,
error for array version:
toStore.val: %15 = "polygeist.pointer2memref"(%14) : (!llvm.ptr<i8>) -> memref<4xi32> isref 0 isar1
cgeist: /home/fahri/projects/Polygeist/tools/cgeist/Lib/ValueCategory.cc:154: void ValueCategory::store(mlir::Location, mlir::OpBuilder&, ValueCategory, bool) const: Assertion `toStore.isReference' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
error for vector version:
CXXBindTemporaryExpr 0x57d38ae5e378 'std::vector<int>':'class std::vector<int>' (CXXTemporary 0x57d38ae5e378)
`-CXXTemporaryObjectExpr 0x57d38ae5e340 'std::vector<int>':'class std::vector<int>' 'void (void) noexcept' list zeroing
cleanup not handled
warning: ignoring __builtin_unreachable
warning, not performing catches for try: CXXTryStmt 0x57d38ae8dfb8
|-CompoundStmt 0x57d38ae8de28
| `-CallExpr 0x57d38ae8ddd8 'int *':'int *'
| |-ImplicitCastExpr 0x57d38ae8ddc0 'int *(*)(int *, unsigned long, allocator<int> &)' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x57d38ae8dd88 'int *(int *, unsigned long, allocator<int> &)' lvalue Function 0x57d38ae75358 '__uninitialized_default_n_a' 'int *(int *, unsigned long, allocator<int> &)' (FunctionTemplate 0x57d38ac2d900 '__uninitialized_default_n_a')
| | `-NestedNameSpecifier Namespace 0x57d38ade9638 'std'
| |-BinaryOperator 0x57d38ae8da68 'pointer':'int *' '+'
| | |-ImplicitCastExpr 0x57d38ae8da38 'pointer':'int *' <LValueToRValue>
| | | `-DeclRefExpr 0x57d38ae8d9f8 'pointer':'int *' lvalue Var 0x57d38ae75aa0 '__new_start' 'pointer':'int *'
| | `-ImplicitCastExpr 0x57d38ae8da50 'size_type':'unsigned long' <LValueToRValue>
| | `-DeclRefExpr 0x57d38ae8da18 'const size_type':'const unsigned long' lvalue Var 0x57d38ae74048 '__size' 'const size_type':'const unsigned long'
| |-ImplicitCastExpr 0x57d38ae8de10 'size_type':'unsigned long' <LValueToRValue>
| | `-DeclRefExpr 0x57d38ae8da88 'size_type':'unsigned long' lvalue ParmVar 0x57d38ae50a78 '__n' 'size_type':'unsigned long'
| `-CXXMemberCallExpr 0x57d38ae8db80 '_Tp_alloc_type':'class std::allocator<int>' lvalue
| `-MemberExpr 0x57d38ae8db38 '<bound member function type>' ->_M_get_Tp_allocator 0x57d38ae36d58
| `-ImplicitCastExpr 0x57d38ae8dba0 'struct std::_Vector_base<int, class std::allocator<int> > *' <UncheckedDerivedToBase (_Vector_base)>
| `-CXXThisExpr 0x57d38ae8db28 'class std::vector<int> *' implicit this
`-CXXCatchStmt 0x57d38ae8df98
|-<<<NULL>>>
`-CompoundStmt 0x57d38ae8df78
|-CXXMemberCallExpr 0x57d38ae8def8 'void'
| |-MemberExpr 0x57d38ae8de70 '<bound member function type>' ->_M_deallocate 0x57d38ae3a998
| | `-ImplicitCastExpr 0x57d38ae8df28 'struct std::_Vector_base<int, class std::allocator<int> > *' <UncheckedDerivedToBase (_Vector_base)>
| | `-CXXThisExpr 0x57d38ae8de60 'class std::vector<int> *' implicit this
| |-ImplicitCastExpr 0x57d38ae8df48 'pointer':'int *' <LValueToRValue>
| | `-DeclRefExpr 0x57d38ae8deb8 'pointer':'int *' lvalue Var 0x57d38ae75aa0 '__new_start' 'pointer':'int *'
| `-ImplicitCastExpr 0x57d38ae8df60 'size_type':'unsigned long' <LValueToRValue>
| `-DeclRefExpr 0x57d38ae8ded8 'const size_type':'const unsigned long' lvalue Var 0x57d38ae758e0 '__len' 'const size_type':'const unsigned long'
`-CXXThrowExpr 0x57d38ae09ea0 'void'
cleanup of materialized not handledBinaryOperator 0x57d38ae9cda0 'unsigned long' '+'
|-CXXMemberCallExpr 0x57d38ae9c708 'size_type':'unsigned long'
| `-MemberExpr 0x57d38ae9c6d8 '<bound member function type>' ->size 0x57d38ae46560
| `-CXXThisExpr 0x57d38ae9c6c8 'const class std::vector<int> *' implicit this
`-ImplicitCastExpr 0x57d38ae9cd88 'unsigned long':'unsigned long' <LValueToRValue>
`-CallExpr 0x57d38ae9cd10 'const unsigned long':'const unsigned long' lvalue
|-ImplicitCastExpr 0x57d38ae9ccf8 'const unsigned long &(*)(const unsigned long &, const unsigned long &)' <FunctionToPointerDecay>
| `-ParenExpr 0x57d38ae9ccb0 'const unsigned long &(const unsigned long &, const unsigned long &)' lvalue
| `-DeclRefExpr 0x57d38ae9cb48 'const unsigned long &(const unsigned long &, const unsigned long &)' lvalue Function 0x57d38ae9ca38 'max' 'const unsigned long &(const unsigned long &, const unsigned long &)' (FunctionTemplate 0x57d38aaed7c0 'max')
| `-NestedNameSpecifier Namespace 0x57d38ac3ebf8 'std'
|-MaterializeTemporaryExpr 0x57d38ae9cd58 'const size_type':'const unsigned long' lvalue
| `-ImplicitCastExpr 0x57d38ae9cd40 'const size_type':'const unsigned long' <NoOp>
| `-CXXMemberCallExpr 0x57d38ae9c7d8 'size_type':'unsigned long'
| `-MemberExpr 0x57d38ae9c7a8 '<bound member function type>' ->size 0x57d38ae46560
| `-CXXThisExpr 0x57d38ae9c798 'const class std::vector<int> *' implicit this
`-ImplicitCastExpr 0x57d38ae9cd70 'const unsigned long':'const unsigned long' lvalue <NoOp>
`-DeclRefExpr 0x57d38ae9c7f8 'size_type':'unsigned long' lvalue ParmVar 0x57d38ae51d90 '__n' 'size_type':'unsigned long'
cleanup not handled
cleanup of materialized not handledCallExpr 0x57d38ae8d4b0 '_Bool'
|-ImplicitCastExpr 0x57d38ae8d498 '_Bool (*)(true_type)' <FunctionToPointerDecay>
| `-DeclRefExpr 0x57d38ae799c0 '_Bool (true_type)' lvalue CXXMethod 0x57d38ae3eea8 '_S_nothrow_relocate' '_Bool (true_type)'
`-CXXConstructExpr 0x57d38ae8d5a0 'true_type':'struct std::integral_constant<_Bool, true>' 'void (integral_constant<_Bool, true> &&) noexcept'
`-ImplicitCastExpr 0x57d38ae8d4f0 'integral_constant<_Bool, true>':'struct std::integral_constant<_Bool, true>' xvalue <DerivedToBase (is_move_constructible -> __is_move_constructible_impl -> __is_constructible_impl -> integral_constant)>
`-MaterializeTemporaryExpr 0x57d38ae8d4d8 '__is_move_insertable<_Tp_alloc_type>':'struct std::__is_move_insertable<class std::allocator<int> >' xvalue
`-CXXFunctionalCastExpr 0x57d38ae79470 '__is_move_insertable<_Tp_alloc_type>':'struct std::__is_move_insertable<class std::allocator<int> >' functional cast to __is_move_insertable<_Tp_alloc_type> <NoOp>
`-InitListExpr 0x57d38ae78e58 '__is_move_insertable<_Tp_alloc_type>':'struct std::__is_move_insertable<class std::allocator<int> >'
`-InitListExpr 0x57d38ae791b0 'is_move_constructible<int>':'struct std::is_move_constructible<int>'
`-InitListExpr 0x57d38ae79238 '__is_move_constructible_impl<int>':'struct std::__is_move_constructible_impl<int>'
`-InitListExpr 0x57d38ae792c0 '__is_constructible_impl<int, int &&>':'struct std::__is_constructible_impl<int, int &&>'
`-InitListExpr 0x57d38ae79348 '__bool_constant<__is_constructible(int, int &&)>':'struct std::integral_constant<_Bool, true>'
cleanup not handled
warning: ignoring __builtin_expect
cgeist: /home/fahri/projects/Polygeist/llvm-project/mlir/lib/IR/PatternMatch.cpp:326: mlir::RewriterBase::eraseOp(mlir::Operation*)::<lambda(mlir::Operation*)>: Assertion `mayBeGraphRegion(*op->getParentRegion()) && "expected that op has no uses"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
I also tried another version of the program using raw pointer and std::array version with output parameter (instead of return) and it works with the following ir output:
module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<i8, dense<8> : vector<2xi32>>, #dlti.dl_entry<i1, dense<8> : vector<2xi32>>, #dlti.dl_entry<!llvm.ptr, dense<64> : vector<4xi32>>, #dlti.dl_entry<f80, dense<128> : vector<2xi32>>, #dlti.dl_entry<i64, dense<64> : vector<2xi32>>, #dlti.dl_entry<!llvm.ptr<272>, dense<64> : vector<4xi32>>, #dlti.dl_entry<!llvm.ptr<271>, dense<32> : vector<4xi32>>, #dlti.dl_entry<!llvm.ptr<270>, dense<32> : vector<4xi32>>, #dlti.dl_entry<f128, dense<128> : vector<2xi32>>, #dlti.dl_entry<f64, dense<64> : vector<2xi32>>, #dlti.dl_entry<f16, dense<16> : vector<2xi32>>, #dlti.dl_entry<i32, dense<32> : vector<2xi32>>, #dlti.dl_entry<i16, dense<16> : vector<2xi32>>, #dlti.dl_entry<"dlti.stack_alignment", 128 : i32>, #dlti.dl_entry<"dlti.endianness", "little">>, llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", llvm.target_triple = "x86_64-unknown-linux-gnu", "polygeist.target-cpu" = "x86-64", "polygeist.target-features" = "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87", "polygeist.tune-cpu" = "generic"} {
func.func @_Z19array_test_templateIiTnDaLi4EEDaRKSt5arrayIT_XT0_EERS2_(%arg0: memref<?x!llvm.struct<(array<4 x i32>)>>, %arg1: memref<?x!llvm.struct<(array<4 x i32>)>>) attributes {llvm.linkage = #llvm.linkage<weak_odr>} {
%c4 = arith.constant 4 : index
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%c1_i32 = arith.constant 1 : i32
scf.for %arg2 = %c0 to %c4 step %c1 {
%0 = arith.index_cast %arg2 : index to i32
%1 = arith.extsi %0 : i32 to i64
%2 = func.call @_ZNSt5arrayIiLm4EEixEm(%arg1, %1) : (memref<?x!llvm.struct<(array<4 x i32>)>>, i64) -> memref<?xi32>
%3 = func.call @_ZNKSt5arrayIiLm4EEixEm(%arg0, %1) : (memref<?x!llvm.struct<(array<4 x i32>)>>, i64) -> memref<?xi32>
%4 = affine.load %3[0] : memref<?xi32>
%5 = arith.addi %4, %c1_i32 : i32
affine.store %5, %2[0] : memref<?xi32>
}
return
}
func.func @_ZNSt5arrayIiLm4EEixEm(%arg0: memref<?x!llvm.struct<(array<4 x i32>)>>, %arg1: i64) -> memref<?xi32> attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
%0 = "polygeist.memref2pointer"(%arg0) : (memref<?x!llvm.struct<(array<4 x i32>)>>) -> !llvm.ptr
%1 = "polygeist.pointer2memref"(%0) : (!llvm.ptr) -> memref<4xi32>
%2 = call @_ZNSt14__array_traitsIiLm4EE6_S_refERA4_Kim(%1, %arg1) : (memref<4xi32>, i64) -> memref<?xi32>
return %2 : memref<?xi32>
}
func.func @_ZNKSt5arrayIiLm4EEixEm(%arg0: memref<?x!llvm.struct<(array<4 x i32>)>>, %arg1: i64) -> memref<?xi32> attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
%0 = "polygeist.memref2pointer"(%arg0) : (memref<?x!llvm.struct<(array<4 x i32>)>>) -> !llvm.ptr
%1 = "polygeist.pointer2memref"(%0) : (!llvm.ptr) -> memref<4xi32>
%2 = call @_ZNSt14__array_traitsIiLm4EE6_S_refERA4_Kim(%1, %arg1) : (memref<4xi32>, i64) -> memref<?xi32>
return %2 : memref<?xi32>
}
func.func @_Z17raw_test_templateIiTnDaLi4EEDaPKT_PS0_(%arg0: memref<?xi32>, %arg1: memref<?xi32>) attributes {llvm.linkage = #llvm.linkage<weak_odr>} {
%c4 = arith.constant 4 : index
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%c1_i32 = arith.constant 1 : i32
scf.for %arg2 = %c0 to %c4 step %c1 {
%0 = memref.load %arg0[%arg2] : memref<?xi32>
%1 = arith.addi %0, %c1_i32 : i32
memref.store %1, %arg1[%arg2] : memref<?xi32>
}
return
}
func.func @_ZNSt14__array_traitsIiLm4EE6_S_refERA4_Kim(%arg0: memref<4xi32>, %arg1: i64) -> memref<?xi32> attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
%0 = arith.index_cast %arg1 : i64 to index
%1 = "polygeist.subindex"(%arg0, %0) : (memref<4xi32>, index) -> memref<?xi32>
return %1 : memref<?xi32>
}
}
I'm not sure what happened, but i think the original program is correct, but somehow cgeist failed to convert to mlir polygeist dialect? Does polygeist fully support c++ template features? Any suggestions would be appreciated. Thank you!
Full test progam:
// test0.cpp
// cgeist test0.cpp --std=c++17 --function="*" -S
// clang test0.cpp --std=c++17 -S
#include <array>
#include <vector>
template<typename T>
auto scalar_test_template(T a)
{
return a + 1;
}
template <typename T, auto N>
auto array_test_template(const std::array<T,N>& array)
{
auto result = std::array<T,N>{};
for (int i=0; i<N; i++) {
result[i] = array[i] + 1;
}
return result;
}
template <typename T, auto N>
auto array_test_template(const std::array<T,N>& array, std::array<T,N>& result)
{
for (int i=0; i<N; i++) {
result[i] = array[i] + 1;
}
}
template <typename T>
auto vector_test_template(const std::vector<T>& array)
{
auto result = std::vector<T>{};
auto N = array.size();
result.resize(N);
for (int i=0; i<N; i++) {
result[i] = array[i] + 1;
}
return result;
}
template <typename T>
auto vector_test_template(const std::vector<T>& array, std::vector<T>& result)
{
auto N = array.size();
if (result.size() != N) {
result.resize(N);
}
for (int i=0; i<N; i++) {
result[i] = array[i] + 1;
}
}
template <typename T, auto N>
auto raw_test_template(const T* array, T* result)
{
for (int i=0; i<N; i++) {
result[i] = array[i] + 1;
}
}
// int version
template auto scalar_test_template<int>(int);
template auto array_test_template<int,4>(const std::array<int,4>&, std::array<int,4>&);
template auto raw_test_template<int,4>(const int*,int*);
// float version
template auto scalar_test_template<float>(float);
template auto array_test_template<float,4>(const std::array<float,4>&, std::array<float,4>&);
template auto raw_test_template<float,4>(const float*,float*);
// Error on cgeist, ok in clang:
// template auto array_test_template<int,4>(const std::array<int,4>&);
// template auto vector_test_template<int>(const std::vector<int>&);
// template auto vector_test_template<int>(const std::vector<int>&, std::vector<int>&);
Metadata
Metadata
Assignees
Labels
No labels