summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Stannard <oliver.stannard@arm.com>2019-03-04 09:17:38 +0000
committerOliver Stannard <oliver.stannard@arm.com>2019-03-04 09:17:38 +0000
commit181afc7f3bb965cac3b911ef6c82519876a68e78 (patch)
tree939b78f330dfea1235ab1713138b6570d37f4959
parent65a401f6a90f8440fed1bcf89b5c3da4d61538a2 (diff)
downloadbcm5719-llvm-181afc7f3bb965cac3b911ef6c82519876a68e78.tar.gz
bcm5719-llvm-181afc7f3bb965cac3b911ef6c82519876a68e78.zip
[ARM] Fix selection of VLDR.16 instruction with imm offset
The isScaledConstantInRange function takes upper and lower bounds which are checked after dividing by the scale, so the bounds checks for half, single and double precision should all be the same. Previously, we had wrong bounds checks for half precision, so selected an immediate the instructions can't actually represent. Differential revision: https://reviews.llvm.org/D58822 llvm-svn: 355305
-rw-r--r--llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp15
-rw-r--r--llvm/test/CodeGen/ARM/fp16-load-store.ll105
2 files changed, 110 insertions, 10 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
index f765334577d..18a123375be 100644
--- a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -119,8 +119,7 @@ public:
SDValue &Offset, SDValue &Opc);
bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc);
- bool IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset,
- int Lwb, int Upb, bool FP16);
+ bool IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset, bool FP16);
bool SelectAddrMode5(SDValue N, SDValue &Base, SDValue &Offset);
bool SelectAddrMode5FP16(SDValue N, SDValue &Base, SDValue &Offset);
bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
@@ -902,7 +901,7 @@ bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
}
bool ARMDAGToDAGISel::IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset,
- int Lwb, int Upb, bool FP16) {
+ bool FP16) {
if (!CurDAG->isBaseWithConstantOffset(N)) {
Base = N;
if (N.getOpcode() == ISD::FrameIndex) {
@@ -924,7 +923,7 @@ bool ARMDAGToDAGISel::IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offse
int RHSC;
const int Scale = FP16 ? 2 : 4;
- if (isScaledConstantInRange(N.getOperand(1), Scale, Lwb, Upb, RHSC)) {
+ if (isScaledConstantInRange(N.getOperand(1), Scale, -255, 256, RHSC)) {
Base = N.getOperand(0);
if (Base.getOpcode() == ISD::FrameIndex) {
int FI = cast<FrameIndexSDNode>(Base)->getIndex();
@@ -962,16 +961,12 @@ bool ARMDAGToDAGISel::IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offse
bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
SDValue &Base, SDValue &Offset) {
- int Lwb = -256 + 1;
- int Upb = 256;
- return IsAddressingMode5(N, Base, Offset, Lwb, Upb, /*FP16=*/ false);
+ return IsAddressingMode5(N, Base, Offset, /*FP16=*/ false);
}
bool ARMDAGToDAGISel::SelectAddrMode5FP16(SDValue N,
SDValue &Base, SDValue &Offset) {
- int Lwb = -512 + 1;
- int Upb = 512;
- return IsAddressingMode5(N, Base, Offset, Lwb, Upb, /*FP16=*/ true);
+ return IsAddressingMode5(N, Base, Offset, /*FP16=*/ true);
}
bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
diff --git a/llvm/test/CodeGen/ARM/fp16-load-store.ll b/llvm/test/CodeGen/ARM/fp16-load-store.ll
new file mode 100644
index 00000000000..4f0003a3e7a
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/fp16-load-store.ll
@@ -0,0 +1,105 @@
+; RUN: llc < %s -mtriple armv8a--none-eabi -mattr=+fullfp16 | FileCheck %s
+
+define void @load_zero(half* %in, half* %out) {
+entry:
+; CHECK-LABEL: load_zero:
+; CHECK: vldr.16 {{s[0-9]+}}, [r0]
+ %arrayidx = getelementptr inbounds half, half* %in, i32 0
+ %load = load half, half* %arrayidx, align 2
+ store half %load, half* %out
+ ret void
+}
+
+define void @load_255(half* %in, half* %out) {
+entry:
+; CHECK-LABEL: load_255:
+; CHECK: vldr.16 {{s[0-9]+}}, [r0, #510]
+ %arrayidx = getelementptr inbounds half, half* %in, i32 255
+ %load = load half, half* %arrayidx, align 2
+ store half %load, half* %out
+ ret void
+}
+
+define void @load_256(half* %in, half* %out) {
+entry:
+; CHECK-LABEL: load_256:
+; CHECK: add [[ADDR:r[0-9]+]], r0, #512
+; CHECK: vldr.16 {{s[0-9]+}}, {{\[}}[[ADDR]]{{\]}}
+ %arrayidx = getelementptr inbounds half, half* %in, i32 256
+ %load = load half, half* %arrayidx, align 2
+ store half %load, half* %out
+ ret void
+}
+
+define void @load_neg_255(half* %in, half* %out) {
+entry:
+; CHECK-LABEL: load_neg_255:
+; CHECK: vldr.16 {{s[0-9]+}}, [r0, #-510]
+ %arrayidx = getelementptr inbounds half, half* %in, i32 -255
+ %load = load half, half* %arrayidx, align 2
+ store half %load, half* %out
+ ret void
+}
+
+define void @load_neg_256(half* %in, half* %out) {
+entry:
+; CHECK-LABEL: load_neg_256:
+; CHECK: sub [[ADDR:r[0-9]+]], r0, #512
+; CHECK: vldr.16 {{s[0-9]+}}, {{\[}}[[ADDR]]{{\]}}
+ %arrayidx = getelementptr inbounds half, half* %in, i32 -256
+ %load = load half, half* %arrayidx, align 2
+ store half %load, half* %out
+ ret void
+}
+
+define void @store_zero(half* %in, half* %out) {
+entry:
+; CHECK-LABEL: store_zero:
+ %load = load half, half* %in, align 2
+; CHECK: vstr.16 {{s[0-9]+}}, [r1]
+ %arrayidx = getelementptr inbounds half, half* %out, i32 0
+ store half %load, half* %arrayidx
+ ret void
+}
+
+define void @store_255(half* %in, half* %out) {
+entry:
+; CHECK-LABEL: store_255:
+ %load = load half, half* %in, align 2
+; CHECK: vstr.16 {{s[0-9]+}}, [r1, #510]
+ %arrayidx = getelementptr inbounds half, half* %out, i32 255
+ store half %load, half* %arrayidx
+ ret void
+}
+
+define void @store_256(half* %in, half* %out) {
+entry:
+; CHECK-LABEL: store_256:
+ %load = load half, half* %in, align 2
+; CHECK: add [[ADDR:r[0-9]+]], r1, #512
+; CHECK: vstr.16 {{s[0-9]+}}, {{\[}}[[ADDR]]{{\]}}
+ %arrayidx = getelementptr inbounds half, half* %out, i32 256
+ store half %load, half* %arrayidx
+ ret void
+}
+
+define void @store_neg_255(half* %in, half* %out) {
+entry:
+; CHECK-LABEL: store_neg_255:
+ %load = load half, half* %in, align 2
+; CHECK: vstr.16 {{s[0-9]+}}, [r1, #-510]
+ %arrayidx = getelementptr inbounds half, half* %out, i32 -255
+ store half %load, half* %arrayidx
+ ret void
+}
+
+define void @store_neg_256(half* %in, half* %out) {
+entry:
+; CHECK-LABEL: store_neg_256:
+ %load = load half, half* %in, align 2
+; CHECK: sub [[ADDR:r[0-9]+]], r1, #512
+; CHECK: vstr.16 {{s[0-9]+}}, {{\[}}[[ADDR]]{{\]}}
+ %arrayidx = getelementptr inbounds half, half* %out, i32 -256
+ store half %load, half* %arrayidx
+ ret void
+}
OpenPOWER on IntegriCloud