[PATCH] [AArch64] Implement allowsUnalignedMemoryAccesses()
Z. Zheng
zhaoshiz at codeaurora.org
Wed Apr 16 18:55:34 PDT 2014
>
> This looks fine to me.
>
> Tim.
>
> http://reviews.llvm.org/D3319
>
>
>
See below for rebased patch and updated test cases.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by
The Linux Foundation
From e1c992f12bfe168a38d5885c91984a9003f07eb7 Mon Sep 17 00:00:00 2001
From: Zhaoshi Zheng <zhaoshiz at codeaurora.org>
Date: Wed, 19 Mar 2014 18:32:22 -0700
Subject: [PATCH 1/3] [AArch64] Implement allowsUnalignedMemoryAccesses()
---
lib/Target/AArch64/AArch64ISelLowering.cpp | 44 ++++++
lib/Target/AArch64/AArch64ISelLowering.h | 6 +
lib/Target/AArch64/AArch64Subtarget.cpp | 34 +++++
lib/Target/AArch64/AArch64Subtarget.h | 7 +
test/CodeGen/AArch64/unaligned-vector-ld1-st1.ll | 172
+++++++++++++++++++++++
5 files changed, 263 insertions(+)
create mode 100644 test/CodeGen/AArch64/unaligned-vector-ld1-st1.ll
diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp
b/lib/Target/AArch64/AArch64ISelLowering.cpp
index 236d5ec..1e79894 100644
--- a/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -4412,6 +4412,50 @@
AArch64TargetLowering::isFMAFasterThanFMulAndFAdd(EVT VT) const {
return false;
}
+
+bool AArch64TargetLowering::allowsUnalignedMemoryAccesses(EVT VT,
+ unsigned
AddrSpace,
+ bool *Fast)
const {
+ const AArch64Subtarget *Subtarget = getSubtarget();
+ // The AllowsUnaliged flag models the SCTLR.A setting in ARM cpus
+ bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
+
+ switch (VT.getSimpleVT().SimpleTy) {
+ default:
+ return false;
+ // Scalar types
+ case MVT::i8: case MVT::i16:
+ case MVT::i32: case MVT::i64:
+ case MVT::f32: case MVT::f64: {
+ // Unaligned access can use (for example) LRDB, LRDH, LDRW
+ if (AllowsUnaligned) {
+ if (Fast)
+ *Fast = true;
+ return true;
+ }
+ return false;
+ }
+ // 64-bit vector types
+ case MVT::v8i8: case MVT::v4i16:
+ case MVT::v2i32: case MVT::v1i64:
+ case MVT::v2f32: case MVT::v1f64:
+ // 128-bit vector types
+ case MVT::v16i8: case MVT::v8i16:
+ case MVT::v4i32: case MVT::v2i64:
+ case MVT::v4f32: case MVT::v2f64: {
+ // For any little-endian targets with neon, we can support unaligned
+ // load/store of V registers using ld1/st1.
+ // A big-endian target may also explicitly support unaligned accesses
+ if (Subtarget->hasNEON() && (AllowsUnaligned || isLittleEndian())) {
+ if (Fast)
+ *Fast = true;
+ return true;
+ }
+ return false;
+ }
+ }
+}
+
// Check whether a shuffle_vector could be presented as concat_vector.
bool AArch64TargetLowering::isConcatVector(SDValue Op, SelectionDAG &DAG,
SDValue V0, SDValue V1,
diff --git a/lib/Target/AArch64/AArch64ISelLowering.h
b/lib/Target/AArch64/AArch64ISelLowering.h
index f83c1ab..154c1d7 100644
--- a/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/lib/Target/AArch64/AArch64ISelLowering.h
@@ -355,6 +355,12 @@ public:
/// expanded to fmul + fadd.
virtual bool isFMAFasterThanFMulAndFAdd(EVT VT) const;
+ /// allowsUnalignedMemoryAccesses - Returns true if the target allows
+ /// unaligned memory accesses of the specified type. Returns whether it
+ /// is "fast" by reference in the second argument.
+ virtual bool allowsUnalignedMemoryAccesses(EVT VT, unsigned AddrSpace,
+ bool *Fast) const;
+
ConstraintType getConstraintType(const std::string &Constraint) const;
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &Info,
diff --git a/lib/Target/AArch64/AArch64Subtarget.cpp
b/lib/Target/AArch64/AArch64Subtarget.cpp
index 9140bbd..53cdf30 100644
--- a/lib/Target/AArch64/AArch64Subtarget.cpp
+++ b/lib/Target/AArch64/AArch64Subtarget.cpp
@@ -25,6 +25,25 @@
using namespace llvm;
+enum AlignMode {
+ DefaultAlign,
+ StrictAlign,
+ NoStrictAlign
+};
+
+static cl::opt<AlignMode>
+Align(cl::desc("Load/store alignment support"),
+ cl::Hidden, cl::init(DefaultAlign),
+ cl::values(
+ clEnumValN(DefaultAlign, "aarch64-default-align",
+ "Generate unaligned accesses only on hardware/OS "
+ "combinations that are known to support them"),
+ clEnumValN(StrictAlign, "aarch64-strict-align",
+ "Disallow all unaligned memory accesses"),
+ clEnumValN(NoStrictAlign, "aarch64-no-strict-align",
+ "Allow unaligned memory accesses"),
+ clEnumValEnd));
+
// Pin the vtable to this file.
void AArch64Subtarget::anchor() {}
@@ -39,6 +58,8 @@ AArch64Subtarget::AArch64Subtarget(StringRef TT,
StringRef CPU, StringRef FS,
void AArch64Subtarget::initializeSubtargetFeatures(StringRef CPU,
StringRef FS) {
+ AllowsUnalignedMem = false;
+
if (CPU.empty())
CPUString = "generic";
@@ -52,6 +73,19 @@ void
AArch64Subtarget::initializeSubtargetFeatures(StringRef CPU,
}
ParseSubtargetFeatures(CPU, FullFS);
+
+ switch (Align) {
+ case DefaultAlign:
+ // Linux targets support unaligned accesses on AARCH64
+ AllowsUnalignedMem = isTargetLinux();
+ break;
+ case StrictAlign:
+ AllowsUnalignedMem = false;
+ break;
+ case NoStrictAlign:
+ AllowsUnalignedMem = true;
+ break;
+ }
}
bool AArch64Subtarget::GVIsIndirectSymbol(const GlobalValue *GV,
diff --git a/lib/Target/AArch64/AArch64Subtarget.h
b/lib/Target/AArch64/AArch64Subtarget.h
index 68c6c4b..45e5a5e 100644
--- a/lib/Target/AArch64/AArch64Subtarget.h
+++ b/lib/Target/AArch64/AArch64Subtarget.h
@@ -38,6 +38,11 @@ protected:
bool HasNEON;
bool HasCrypto;
+ /// AllowsUnalignedMem - If true, the subtarget allows unaligned memory
+ /// accesses for some types. For details, see
+ /// AArch64TargetLowering::allowsUnalignedMemoryAccesses().
+ bool AllowsUnalignedMem;
+
/// TargetTriple - What processor and OS we're targeting.
Triple TargetTriple;
@@ -74,6 +79,8 @@ public:
bool hasNEON() const { return HasNEON; }
bool hasCrypto() const { return HasCrypto; }
+ bool allowsUnalignedMem() const { return AllowsUnalignedMem; }
+
bool isLittle() const { return IsLittleEndian; }
const std::string & getCPUString() const { return CPUString; }
diff --git a/test/CodeGen/AArch64/unaligned-vector-ld1-st1.ll
b/test/CodeGen/AArch64/unaligned-vector-ld1-st1.ll
new file mode 100644
index 0000000..2e3f7bf
--- /dev/null
+++ b/test/CodeGen/AArch64/unaligned-vector-ld1-st1.ll
@@ -0,0 +1,172 @@
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+neon -o - |
FileCheck %s
+; RUN: llc < %s -mtriple=aarch64_be-none-linux-gnu -mattr=+neon -o - |
FileCheck %s
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -aarch64-no-strict-align
-mattr=+neon -o - | FileCheck %s
+; RUN: llc < %s -mtriple=aarch64_be-none-linux-gnu
-aarch64-no-strict-align -mattr=+neon -o - | FileCheck %s
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -aarch64-strict-align
-mattr=+neon -o - | FileCheck %s
+; RUN: llc < %s -mtriple=aarch64_be-none-linux-gnu -aarch64-strict-align
-mattr=+neon -o - | FileCheck %s --check-prefix=BE-STRICT-ALIGN
+
+;; Check element-aligned 128-bit vector load/store - integer
+define <16 x i8> @qwordint (<16 x i8>* %head.v16i8, <8 x i16>*
%head.v8i16, <4 x i32>* %head.v4i32, <2 x i64>* %head.v2i64,
+ <16 x i8>* %tail.v16i8, <8 x i16>*
%tail.v8i16, <4 x i32>* %tail.v4i32, <2 x i64>* %tail.v2i64) {
+; CHECK-LABEL: qwordint
+; CHECK: ld1 {v0.16b}, [x0]
+; CHECK: ld1 {v1.8h}, [x1]
+; CHECK: ld1 {v2.4s}, [x2]
+; CHECK: ld1 {v3.2d}, [x3]
+; CHECK: st1 {v0.16b}, [x4]
+; CHECK: st1 {v1.8h}, [x5]
+; CHECK: st1 {v2.4s}, [x6]
+; CHECK: st1 {v3.2d}, [x7]
+; BE-STRICT-ALIGN-LABEL: qwordint
+; BE-STRICT-ALIGN: ldrb
+; BE-STRICT-ALIGN: ldrh
+; BE-STRICT-ALIGN: ldr
+; BE-STRICT-ALIGN: ldr
+; BE-STRICT-ALIGN: strb
+; BE-STRICT-ALIGN: strh
+; BE-STRICT-ALIGN: str
+; BE-STRICT-ALIGN: str
+entry:
+ %val.v16i8 = load <16 x i8>* %head.v16i8, align 1
+ %val.v8i16 = load <8 x i16>* %head.v8i16, align 2
+ %val.v4i32 = load <4 x i32>* %head.v4i32, align 4
+ %val.v2i64 = load <2 x i64>* %head.v2i64, align 8
+ store <16 x i8> %val.v16i8, <16 x i8>* %tail.v16i8, align 1
+ store <8 x i16> %val.v8i16, <8 x i16>* %tail.v8i16, align 2
+ store <4 x i32> %val.v4i32, <4 x i32>* %tail.v4i32, align 4
+ store <2 x i64> %val.v2i64, <2 x i64>* %tail.v2i64, align 8
+ ret <16 x i8> %val.v16i8
+}
+
+;; Check element-aligned 128-bit vector load/store - floating point
+define <4 x float> @qwordfloat (<4 x float>* %head.v4f32, <2 x double>*
%head.v2f64,
+ <4 x float>* %tail.v4f32, <2 x double>*
%tail.v2f64) {
+; CHECK-LABEL: qwordfloat
+; CHECK: ld1 {v0.4s}, [x0]
+; CHECK: ld1 {v1.2d}, [x1]
+; CHECK: st1 {v0.4s}, [x2]
+; CHECK: st1 {v1.2d}, [x3]
+; BE-STRICT-ALIGN-LABEL: qwordfloat
+; BE-STRICT-ALIGN: ldr
+; BE-STRICT-ALIGN: ldr
+; BE-STRICT-ALIGN: str
+; BE-STRICT-ALIGN: str
+entry:
+ %val.v4f32 = load <4 x float>* %head.v4f32, align 4
+ %val.v2f64 = load <2 x double>* %head.v2f64, align 8
+ store <4 x float> %val.v4f32, <4 x float>* %tail.v4f32, align 4
+ store <2 x double> %val.v2f64, <2 x double>* %tail.v2f64, align 8
+ ret <4 x float> %val.v4f32
+}
+
+;; Check element-aligned 64-bit vector load/store - integer
+define <8 x i8> @dwordint (<8 x i8>* %head.v8i8, <4 x i16>*
%head.v4i16, <2 x i32>* %head.v2i32, <1 x i64>* %head.v1i64,
+ <8 x i8>* %tail.v8i8, <4 x i16>*
%tail.v4i16, <2 x i32>* %tail.v2i32, <1 x i64>* %tail.v1i64) {
+; CHECK-LABEL: dwordint
+; CHECK: ld1 {v0.8b}, [x0]
+; CHECK: ld1 {v1.4h}, [x1]
+; CHECK: ld1 {v2.2s}, [x2]
+; CHECK: ld1 {v3.1d}, [x3]
+; CHECK: st1 {v0.8b}, [x4]
+; CHECK: st1 {v1.4h}, [x5]
+; CHECK: st1 {v2.2s}, [x6]
+; CHECK: st1 {v3.1d}, [x7]
+; BE-STRICT-ALIGN-LABEL: dwordint
+; BE-STRICT-ALIGN: ldrb
+; BE-STRICT-ALIGN: ldrh
+; BE-STRICT-ALIGN: ldr
+; BE-STRICT-ALIGN: ld1 {v1.1d}, [x3]
+; BE-STRICT-ALIGN: strb
+; BE-STRICT-ALIGN: strh
+; BE-STRICT-ALIGN: str
+; BE-STRICT-ALIGN: st1 {v1.1d}, [x7]
+entry:
+ %val.v8i8 = load <8 x i8>* %head.v8i8, align 1
+ %val.v4i16 = load <4 x i16>* %head.v4i16, align 2
+ %val.v2i32 = load <2 x i32>* %head.v2i32, align 4
+ %val.v1i64 = load <1 x i64>* %head.v1i64, align 8
+ store <8 x i8> %val.v8i8, <8 x i8>* %tail.v8i8 , align 1
+ store <4 x i16> %val.v4i16, <4 x i16>* %tail.v4i16, align 2
+ store <2 x i32> %val.v2i32, <2 x i32>* %tail.v2i32, align 4
+ store <1 x i64> %val.v1i64, <1 x i64>* %tail.v1i64, align 8
+ ret <8 x i8> %val.v8i8
+}
+
+;; Check element-aligned 64-bit vector load/store - floating point
+define <2 x float> @dwordfloat (<2 x float>* %head.v2f32, <1 x double>*
%head.v1f64,
+ <2 x float>* %tail.v2f32, <1 x double>*
%tail.v1f64) {
+; CHECK-LABEL: dwordfloat
+; CHECK: ld1 {v0.2s}, [x0]
+; CHECK: ld1 {v1.1d}, [x1]
+; CHECK: st1 {v0.2s}, [x2]
+; CHECK: st1 {v1.1d}, [x3]
+; BE-STRICT-ALIGN-LABEL: dwordfloat
+; BE-STRICT-ALIGN: ldr
+; BE-STRICT-ALIGN: ld1 {v1.1d}, [x1]
+; BE-STRICT-ALIGN: str
+; BE-STRICT-ALIGN: st1 {v1.1d}, [x3]
+entry:
+ %val.v2f32 = load <2 x float>* %head.v2f32, align 4
+ %val.v1f64 = load <1 x double>* %head.v1f64, align 8
+ store <2 x float> %val.v2f32, <2 x float>* %tail.v2f32, align 4
+ store <1 x double> %val.v1f64, <1 x double>* %tail.v1f64, align 8
+ ret <2 x float> %val.v2f32
+}
+
+;; Check load/store of 128-bit vectors with less-than 16-byte alignment
+define <2 x i64> @align2vi64 (<2 x i64>* %head.byte, <2 x i64>*
%head.half, <2 x i64>* %head.word, <2 x i64>* %head.dword,
+ <2 x i64>* %tail.byte, <2 x i64>*
%tail.half, <2 x i64>* %tail.word, <2 x i64>* %tail.dword) {
+; CHECK-LABEL: align2vi64
+; CHECK: ld1 {v0.2d}, [x0]
+; CHECK: ld1 {v1.2d}, [x1]
+; CHECK: ld1 {v2.2d}, [x2]
+; CHECK: ld1 {v3.2d}, [x3]
+; CHECK: st1 {v0.2d}, [x4]
+; CHECK: st1 {v1.2d}, [x5]
+; CHECK: st1 {v2.2d}, [x6]
+; CHECK: st1 {v3.2d}, [x7]
+; BE-STRICT-ALIGN-LABEL: align2vi64
+; BE-STRICT-ALIGN: ldrb
+; BE-STRICT-ALIGN: ldrh
+; BE-STRICT-ALIGN: ldr
+; BE-STRICT-ALIGN: strb
+; BE-STRICT-ALIGN: strh
+; BE-STRICT-ALIGN: str
+entry:
+ %val.byte = load <2 x i64>* %head.byte, align 1
+ %val.half = load <2 x i64>* %head.half, align 2
+ %val.word = load <2 x i64>* %head.word, align 4
+ %val.dword = load <2 x i64>* %head.dword, align 8
+ store <2 x i64> %val.byte, <2 x i64>* %tail.byte, align 1
+ store <2 x i64> %val.half, <2 x i64>* %tail.half, align 2
+ store <2 x i64> %val.word, <2 x i64>* %tail.word, align 4
+ store <2 x i64> %val.dword, <2 x i64>* %tail.dword, align 8
+ ret <2 x i64> %val.byte
+}
+
+;; Check load/store of 64-bit vectors with less-than 8-byte alignment
+define <2 x float> @align2vf32 (<2 x float>* %head.byte, <2 x float>*
%head.half, <2 x float>* %head.word, <2 x float>* %head.dword,
+ <2 x float>* %tail.byte, <2 x float>*
%tail.half, <2 x float>* %tail.word, <2 x float>* %tail.dword) {
+; CHECK-LABEL: align2vf32
+; CHECK: ld1 {v0.2s}, [x0]
+; CHECK: ld1 {v1.2s}, [x1]
+; CHECK: ld1 {v2.2s}, [x2]
+; CHECK: st1 {v0.2s}, [x4]
+; CHECK: st1 {v1.2s}, [x5]
+; CHECK: st1 {v2.2s}, [x6]
+; BE-STRICT-ALIGN-LABEL: align2vf32
+; BE-STRICT-ALIGN: ldrb
+; BE-STRICT-ALIGN: ldrh
+; BE-STRICT-ALIGN: ldr
+; BE-STRICT-ALIGN: strb
+; BE-STRICT-ALIGN: strh
+; BE-STRICT-ALIGN: str
+entry:
+ %val.byte = load <2 x float>* %head.byte, align 1
+ %val.half = load <2 x float>* %head.half, align 2
+ %val.word = load <2 x float>* %head.word, align 4
+ store <2 x float> %val.byte, <2 x float>* %tail.byte, align 1
+ store <2 x float> %val.half, <2 x float>* %tail.half, align 2
+ store <2 x float> %val.word, <2 x float>* %tail.word, align 4
+ ret <2 x float> %val.byte
+}
- {F54319, layout=link}
http://reviews.llvm.org/D3319
More information about the llvm-commits
mailing list