]> granicus.if.org Git - llvm/commitdiff
[ARM] Fix selection of VLDR.16 instruction with imm offset
authorOliver Stannard <oliver.stannard@arm.com>
Mon, 4 Mar 2019 09:17:38 +0000 (09:17 +0000)
committerOliver Stannard <oliver.stannard@arm.com>
Mon, 4 Mar 2019 09:17:38 +0000 (09:17 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355305 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMISelDAGToDAG.cpp
test/CodeGen/ARM/fp16-load-store.ll [new file with mode: 0644]

index f765334577db7b9f961dd69a238095f357f0499b..18a123375be91fea3969eac0e4edf8053b6b80e4 100644 (file)
@@ -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/test/CodeGen/ARM/fp16-load-store.ll b/test/CodeGen/ARM/fp16-load-store.ll
new file mode 100644 (file)
index 0000000..4f0003a
--- /dev/null
@@ -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
+}