1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[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
This commit is contained in:
Oliver Stannard 2019-03-04 09:17:38 +00:00
parent a58dcdaa5e
commit 480fa6448d
2 changed files with 110 additions and 10 deletions

View File

@ -119,8 +119,7 @@ public:
SDValue &Offset, SDValue &Opc); SDValue &Offset, SDValue &Opc);
bool SelectAddrMode3Offset(SDNode *Op, SDValue N, bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc); SDValue &Offset, SDValue &Opc);
bool IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset, bool IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset, bool FP16);
int Lwb, int Upb, bool FP16);
bool SelectAddrMode5(SDValue N, SDValue &Base, SDValue &Offset); bool SelectAddrMode5(SDValue N, SDValue &Base, SDValue &Offset);
bool SelectAddrMode5FP16(SDValue N, SDValue &Base, SDValue &Offset); bool SelectAddrMode5FP16(SDValue N, SDValue &Base, SDValue &Offset);
bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align); 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, bool ARMDAGToDAGISel::IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset,
int Lwb, int Upb, bool FP16) { bool FP16) {
if (!CurDAG->isBaseWithConstantOffset(N)) { if (!CurDAG->isBaseWithConstantOffset(N)) {
Base = N; Base = N;
if (N.getOpcode() == ISD::FrameIndex) { if (N.getOpcode() == ISD::FrameIndex) {
@ -924,7 +923,7 @@ bool ARMDAGToDAGISel::IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offse
int RHSC; int RHSC;
const int Scale = FP16 ? 2 : 4; 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); Base = N.getOperand(0);
if (Base.getOpcode() == ISD::FrameIndex) { if (Base.getOpcode() == ISD::FrameIndex) {
int FI = cast<FrameIndexSDNode>(Base)->getIndex(); int FI = cast<FrameIndexSDNode>(Base)->getIndex();
@ -962,16 +961,12 @@ bool ARMDAGToDAGISel::IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offse
bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N, bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
SDValue &Base, SDValue &Offset) { SDValue &Base, SDValue &Offset) {
int Lwb = -256 + 1; return IsAddressingMode5(N, Base, Offset, /*FP16=*/ false);
int Upb = 256;
return IsAddressingMode5(N, Base, Offset, Lwb, Upb, /*FP16=*/ false);
} }
bool ARMDAGToDAGISel::SelectAddrMode5FP16(SDValue N, bool ARMDAGToDAGISel::SelectAddrMode5FP16(SDValue N,
SDValue &Base, SDValue &Offset) { SDValue &Base, SDValue &Offset) {
int Lwb = -512 + 1; return IsAddressingMode5(N, Base, Offset, /*FP16=*/ true);
int Upb = 512;
return IsAddressingMode5(N, Base, Offset, Lwb, Upb, /*FP16=*/ true);
} }
bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr, bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,

View File

@ -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
}