[AArch64] NFC: Add generic StackOffset to describe scalable offsets.
To support spilling/filling of scalable vectors we need a more generic
representation of a stack offset than simply 'int'.
For this we introduce the StackOffset struct, which comprises multiple
offsets sized by their respective MVTs. Byte-offsets will thus be a simple
tuple such as { offset, MVT::i8 }. Adding two byte-offsets will result in a
byte offset { offsetA + offsetB, MVT::i8 }. When two offsets have different
types, we can canonicalise them to use the same MVT, as long as their
runtime sizes are guaranteed to have the same size-ratio as they would have
at compile-time.
When we have both scalable- and fixed-size objects on the stack, we can
create an offset that is:
({ offset_fixed, MVT::i8 } + { offset_scalable, MVT::nxv1i8 })
The struct also contains a getForFrameOffset() method that is specific to
AArch64 and decomposes the frame-offset to be used directly in instructions
that operate on the stack or index into the stack.
Note: This patch adds StackOffset as an AArch64-only concept, but we would
like to make this a generic concept/struct that is supported by all
interfaces that take or return stack offsets (currently as 'int'). Since
that would be a bigger change that is currently pending on D32530 landing,
we thought it makes sense to first show/prove the concept in the AArch64
target before proposing to roll this out further.
Reviewers: thegameg, rovka, t.p.northover, efriedma, greened
Reviewed By: rovka, greened
Differential Revision: https://reviews.llvm.org/D61435
llvm-svn: 368024
diff --git a/llvm/unittests/Target/AArch64/TestStackOffset.cpp b/llvm/unittests/Target/AArch64/TestStackOffset.cpp
new file mode 100644
index 0000000..240cec9
--- /dev/null
+++ b/llvm/unittests/Target/AArch64/TestStackOffset.cpp
@@ -0,0 +1,60 @@
+//===- TestStackOffset.cpp - StackOffset unit tests------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "AArch64StackOffset.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+TEST(StackOffset, MixedSize) {
+ StackOffset A(1, MVT::i8);
+ EXPECT_EQ(1, A.getBytes());
+
+ StackOffset B(2, MVT::i32);
+ EXPECT_EQ(8, B.getBytes());
+
+ StackOffset C(2, MVT::v4i64);
+ EXPECT_EQ(64, C.getBytes());
+}
+
+TEST(StackOffset, Add) {
+ StackOffset A(1, MVT::i64);
+ StackOffset B(1, MVT::i32);
+ StackOffset C = A + B;
+ EXPECT_EQ(12, C.getBytes());
+
+ StackOffset D(1, MVT::i32);
+ D += A;
+ EXPECT_EQ(12, D.getBytes());
+}
+
+TEST(StackOffset, Sub) {
+ StackOffset A(1, MVT::i64);
+ StackOffset B(1, MVT::i32);
+ StackOffset C = A - B;
+ EXPECT_EQ(4, C.getBytes());
+
+ StackOffset D(1, MVT::i64);
+ D -= A;
+ EXPECT_EQ(0, D.getBytes());
+}
+
+TEST(StackOffset, isZero) {
+ StackOffset A(0, MVT::i64);
+ StackOffset B(0, MVT::i32);
+ EXPECT_TRUE(!A);
+ EXPECT_TRUE(!(A + B));
+}
+
+TEST(StackOffset, getForFrameOffset) {
+ StackOffset A(1, MVT::i64);
+ StackOffset B(1, MVT::i32);
+ int64_t ByteSized;
+ (A + B).getForFrameOffset(ByteSized);
+ EXPECT_EQ(12, ByteSized);
+}