Skip to content

Commit 63b2ff0

Browse files
[mlir] Add padding to 1-D Vector in CRunnerUtils.h
Summary: This revision fixes a -Wzero-length-array compile error that caused e459596 which reverted 78f9e5d. Also fixes a struct vs class mismatch that broke compilation with -Werror for Windows that caused 57397eb. This revision adds padding for 1-D Vector in the common case of x86 execution with a stadard data layout. This supports properly interfacing codegen with arrays of e.g. `vector<9xf32>`. Such vectors are already assumed padded to the next power of 2 by LLVM codegen with the default x86 data layout: ``` define void @test_vector_add_1d_2_3(<3 x float>* nocapture readnone %0, <3 x float>* nocapture readonly %1, i64 %2, i64 %3, i64 %4, <3 x float>* nocapture readnone %5, <3 x float>* nocapture readonly %6, i64 %7, i64 %8, i64 %9, <3 x float>* nocapture readnone %10, <3 x float>* nocapture %11, i64 %12, i64 %13, i64 %14) local_unnamed_addr { %16 = getelementptr <3 x float>, <3 x float>* %6, i64 1 %17 = load <3 x float>, <3 x float>* %16, align 16 %18 = getelementptr <3 x float>, <3 x float>* %1, i64 1 %19 = load <3 x float>, <3 x float>* %18, align 16 %20 = fadd <3 x float> %17, %19 %21 = getelementptr <3 x float>, <3 x float>* %11, i64 1 ``` The pointer addressing a `vector<3xf32>` is assumed aligned `@16`. Similarly, the pointer addressing a `vector<65xf32>` is assumed aligned `@512`. This revision allows using objects such as `vector<3xf32>` properly with the standard x86 data layout used in the JitRunner. Integration testing is done out of tree, at the moment such testing fails without this change. Differential Revision: https://reviews.llvm.org/D75459
1 parent 9a8f296 commit 63b2ff0

File tree

2 files changed

+69
-6
lines changed

2 files changed

+69
-6
lines changed

mlir/include/mlir/ExecutionEngine/CRunnerUtils.h

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,78 @@ template <int N> void dropFront(int64_t arr[N], int64_t *res) {
3939
//===----------------------------------------------------------------------===//
4040
// Codegen-compatible structures for Vector type.
4141
//===----------------------------------------------------------------------===//
42+
namespace detail {
43+
template <unsigned N>
44+
constexpr bool isPowerOf2() {
45+
return (!(N & (N - 1)));
46+
}
47+
48+
template <unsigned N>
49+
constexpr unsigned nextPowerOf2();
50+
template <>
51+
constexpr unsigned nextPowerOf2<0>() {
52+
return 1;
53+
}
54+
template <>
55+
constexpr unsigned nextPowerOf2<1>() {
56+
return 1;
57+
}
58+
template <unsigned N> constexpr unsigned nextPowerOf2() {
59+
return isPowerOf2<N>() ? N : 2 * nextPowerOf2<(N + 1) / 2>();
60+
}
61+
62+
template <typename T, int Dim, bool IsPowerOf2>
63+
struct Vector1D;
64+
65+
template <typename T, int Dim>
66+
struct Vector1D<T, Dim, /*IsPowerOf2=*/true> {
67+
Vector1D() {
68+
static_assert(detail::nextPowerOf2<sizeof(T[Dim])>() == sizeof(T[Dim]),
69+
"size error");
70+
}
71+
constexpr T &operator[](unsigned i) { return vector[i]; }
72+
constexpr const T &operator[](unsigned i) const { return vector[i]; }
73+
74+
private:
75+
T vector[Dim];
76+
};
77+
78+
// 1-D vector, padded to the next power of 2 allocation.
79+
// Specialization occurs to avoid zero size arrays (which fail in -Werror).
80+
template <typename T, int Dim>
81+
struct Vector1D<T, Dim, /*IsPowerOf2=*/false> {
82+
Vector1D() {
83+
static_assert(detail::nextPowerOf2<sizeof(T[Dim])>() > sizeof(T[Dim]),
84+
"size error");
85+
static_assert(detail::nextPowerOf2<sizeof(T[Dim])>() < 2 * sizeof(T[Dim]),
86+
"size error");
87+
}
88+
constexpr T &operator[](unsigned i) { return vector[i]; }
89+
constexpr const T &operator[](unsigned i) const { return vector[i]; }
90+
91+
private:
92+
T vector[Dim];
93+
char padding[detail::nextPowerOf2<sizeof(T[Dim])>() - sizeof(T[Dim])];
94+
};
95+
} // end namespace detail
96+
97+
// N-D vectors recurse down to 1-D.
4298
template <typename T, int Dim, int... Dims>
4399
struct Vector {
100+
constexpr Vector<T, Dims...> &operator[](unsigned i) { return vector[i]; }
101+
constexpr const Vector<T, Dims...> &operator[](unsigned i) const {
102+
return vector[i];
103+
}
104+
105+
private:
44106
Vector<T, Dims...> vector[Dim];
45107
};
46108

109+
// 1-D vectors in LLVM are automatically padded to the next power of 2.
110+
// We insert explicit padding in to account for this.
47111
template <typename T, int Dim>
48-
struct Vector<T, Dim> {
49-
T vector[Dim];
50-
};
112+
struct Vector<T, Dim>
113+
: public detail::Vector1D<T, Dim, detail::isPowerOf2<sizeof(T[Dim])>()> {};
51114

52115
template <int D1, typename T>
53116
using Vector1D = Vector<T, D1>;

mlir/include/mlir/ExecutionEngine/RunnerUtils.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,22 @@ void VectorDataPrinter<T, M, Dims...>::print(std::ostream &os,
9292
static_assert(sizeof(val) == M * StaticSizeMult<Dims...>::value * sizeof(T),
9393
"Incorrect vector size!");
9494
// First
95-
os << "(" << val.vector[0];
95+
os << "(" << val[0];
9696
if (M > 1)
9797
os << ", ";
9898
if (sizeof...(Dims) > 1)
9999
os << "\n";
100100
// Kernel
101101
for (unsigned i = 1; i + 1 < M; ++i) {
102102
printSpace(os, 2 * sizeof...(Dims));
103-
os << val.vector[i] << ", ";
103+
os << val[i] << ", ";
104104
if (sizeof...(Dims) > 1)
105105
os << "\n";
106106
}
107107
// Last
108108
if (M > 1) {
109109
printSpace(os, sizeof...(Dims));
110-
os << val.vector[M - 1];
110+
os << val[M - 1];
111111
}
112112
os << ")";
113113
}

0 commit comments

Comments
 (0)