[llvm] r322663 - [AArch64] Fix incorrect LD1 of 16-bit FP vectors in big endian
Pablo Barrio via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 17 06:39:29 PST 2018
Author: pabbar01
Date: Wed Jan 17 06:39:29 2018
New Revision: 322663
URL: http://llvm.org/viewvc/llvm-project?rev=322663&view=rev
Log:
[AArch64] Fix incorrect LD1 of 16-bit FP vectors in big endian
Summary:
Loading a vector of 4 half-precision FP sometimes results in an LD1
of 2 single-precision FP + a reversal. This results in an incorrect
byte swap due to the conversion from little endian to big endian.
In order to generate the correct byte swap, it is easier to
generate the correct LD1 of 4 half-precision FP, thus avoiding the
subsequent reversal.
Reviewers: craig.topper, jmolloy, olista01
Reviewed By: olista01
Subscribers: efriedma, samparker, SjoerdMeijer, rogfer01, aemerson, rengolin, javed.absar, kristof.beyls, llvm-commits
Differential Revision: https://reviews.llvm.org/D41863
Modified:
llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td
llvm/trunk/test/CodeGen/AArch64/arm64-big-endian-bitconverts.ll
Modified: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td?rev=322663&r1=322662&r2=322663&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td Wed Jan 17 06:39:29 2018
@@ -5807,7 +5807,7 @@ def : Pat<(v2i32 (bitconvert (f64 FPR6
def : Pat<(v2i32 (bitconvert (v1f64 FPR64:$src))),
(v2i32 (REV64v2i32 FPR64:$src))>;
def : Pat<(v2i32 (bitconvert (v4f16 FPR64:$src))),
- (v2i32 (REV64v4i16 FPR64:$src))>;
+ (v2i32 (REV32v4i16 FPR64:$src))>;
}
def : Pat<(v2i32 (bitconvert (v2f32 FPR64:$src))), (v2i32 FPR64:$src)>;
@@ -5816,7 +5816,6 @@ def : Pat<(v4i16 (bitconvert (v1i64 FPR6
def : Pat<(v4i16 (bitconvert (v2i32 FPR64:$src))), (v4i16 FPR64:$src)>;
def : Pat<(v4i16 (bitconvert (v8i8 FPR64:$src))), (v4i16 FPR64:$src)>;
def : Pat<(v4i16 (bitconvert (f64 FPR64:$src))), (v4i16 FPR64:$src)>;
-def : Pat<(v4i16 (bitconvert (v4f16 FPR64:$src))), (v4i16 FPR64:$src)>;
def : Pat<(v4i16 (bitconvert (v2f32 FPR64:$src))), (v4i16 FPR64:$src)>;
def : Pat<(v4i16 (bitconvert (v1f64 FPR64:$src))), (v4i16 FPR64:$src)>;
}
@@ -5829,18 +5828,16 @@ def : Pat<(v4i16 (bitconvert (v8i8 FPR6
(v4i16 (REV16v8i8 FPR64:$src))>;
def : Pat<(v4i16 (bitconvert (f64 FPR64:$src))),
(v4i16 (REV64v4i16 FPR64:$src))>;
-def : Pat<(v4i16 (bitconvert (v4f16 FPR64:$src))),
- (v4i16 (REV32v4i16 FPR64:$src))>;
def : Pat<(v4i16 (bitconvert (v2f32 FPR64:$src))),
(v4i16 (REV32v4i16 FPR64:$src))>;
def : Pat<(v4i16 (bitconvert (v1f64 FPR64:$src))),
(v4i16 (REV64v4i16 FPR64:$src))>;
}
+def : Pat<(v4i16 (bitconvert (v4f16 FPR64:$src))), (v4i16 FPR64:$src)>;
let Predicates = [IsLE] in {
def : Pat<(v4f16 (bitconvert (v1i64 FPR64:$src))), (v4f16 FPR64:$src)>;
def : Pat<(v4f16 (bitconvert (v2i32 FPR64:$src))), (v4f16 FPR64:$src)>;
-def : Pat<(v4f16 (bitconvert (v4i16 FPR64:$src))), (v4f16 FPR64:$src)>;
def : Pat<(v4f16 (bitconvert (v8i8 FPR64:$src))), (v4f16 FPR64:$src)>;
def : Pat<(v4f16 (bitconvert (f64 FPR64:$src))), (v4f16 FPR64:$src)>;
def : Pat<(v4f16 (bitconvert (v2f32 FPR64:$src))), (v4f16 FPR64:$src)>;
@@ -5850,20 +5847,17 @@ let Predicates = [IsBE] in {
def : Pat<(v4f16 (bitconvert (v1i64 FPR64:$src))),
(v4f16 (REV64v4i16 FPR64:$src))>;
def : Pat<(v4f16 (bitconvert (v2i32 FPR64:$src))),
- (v4f16 (REV64v4i16 FPR64:$src))>;
-def : Pat<(v4f16 (bitconvert (v4i16 FPR64:$src))),
- (v4f16 (REV64v4i16 FPR64:$src))>;
+ (v4f16 (REV32v4i16 FPR64:$src))>;
def : Pat<(v4f16 (bitconvert (v8i8 FPR64:$src))),
(v4f16 (REV16v8i8 FPR64:$src))>;
def : Pat<(v4f16 (bitconvert (f64 FPR64:$src))),
(v4f16 (REV64v4i16 FPR64:$src))>;
def : Pat<(v4f16 (bitconvert (v2f32 FPR64:$src))),
- (v4f16 (REV64v4i16 FPR64:$src))>;
+ (v4f16 (REV32v4i16 FPR64:$src))>;
def : Pat<(v4f16 (bitconvert (v1f64 FPR64:$src))),
(v4f16 (REV64v4i16 FPR64:$src))>;
}
-
-
+def : Pat<(v4f16 (bitconvert (v4i16 FPR64:$src))), (v4f16 FPR64:$src)>;
let Predicates = [IsLE] in {
def : Pat<(v8i8 (bitconvert (v1i64 FPR64:$src))), (v8i8 FPR64:$src)>;
@@ -5955,7 +5949,7 @@ def : Pat<(v2f32 (bitconvert (v1f64 FPR6
def : Pat<(v2f32 (bitconvert (f64 FPR64:$src))),
(v2f32 (REV64v2i32 FPR64:$src))>;
def : Pat<(v2f32 (bitconvert (v4f16 FPR64:$src))),
- (v2f32 (REV64v4i16 FPR64:$src))>;
+ (v2f32 (REV32v4i16 FPR64:$src))>;
}
def : Pat<(v2f32 (bitconvert (v2i32 FPR64:$src))), (v2f32 FPR64:$src)>;
@@ -6098,7 +6092,6 @@ def : Pat<(v8i16 (bitconvert (v4i32 FPR1
def : Pat<(v8i16 (bitconvert (v16i8 FPR128:$src))), (v8i16 FPR128:$src)>;
def : Pat<(v8i16 (bitconvert (v2f64 FPR128:$src))), (v8i16 FPR128:$src)>;
def : Pat<(v8i16 (bitconvert (v4f32 FPR128:$src))), (v8i16 FPR128:$src)>;
-def : Pat<(v8i16 (bitconvert (v8f16 FPR128:$src))), (v8i16 FPR128:$src)>;
}
let Predicates = [IsBE] in {
def : Pat<(v8i16 (bitconvert (f128 FPR128:$src))),
@@ -6115,15 +6108,13 @@ def : Pat<(v8i16 (bitconvert (v2f64 FPR1
(v8i16 (REV64v8i16 FPR128:$src))>;
def : Pat<(v8i16 (bitconvert (v4f32 FPR128:$src))),
(v8i16 (REV32v8i16 FPR128:$src))>;
-def : Pat<(v8i16 (bitconvert (v8f16 FPR128:$src))),
- (v8i16 (REV32v8i16 FPR128:$src))>;
}
+def : Pat<(v8i16 (bitconvert (v8f16 FPR128:$src))), (v8i16 FPR128:$src)>;
let Predicates = [IsLE] in {
def : Pat<(v8f16 (bitconvert (f128 FPR128:$src))), (v8f16 FPR128:$src)>;
def : Pat<(v8f16 (bitconvert (v2i64 FPR128:$src))), (v8f16 FPR128:$src)>;
def : Pat<(v8f16 (bitconvert (v4i32 FPR128:$src))), (v8f16 FPR128:$src)>;
-def : Pat<(v8f16 (bitconvert (v8i16 FPR128:$src))), (v8f16 FPR128:$src)>;
def : Pat<(v8f16 (bitconvert (v16i8 FPR128:$src))), (v8f16 FPR128:$src)>;
def : Pat<(v8f16 (bitconvert (v2f64 FPR128:$src))), (v8f16 FPR128:$src)>;
def : Pat<(v8f16 (bitconvert (v4f32 FPR128:$src))), (v8f16 FPR128:$src)>;
@@ -6137,8 +6128,6 @@ def : Pat<(v8f16 (bitconvert (v2i64 FPR1
(v8f16 (REV64v8i16 FPR128:$src))>;
def : Pat<(v8f16 (bitconvert (v4i32 FPR128:$src))),
(v8f16 (REV32v8i16 FPR128:$src))>;
-def : Pat<(v8f16 (bitconvert (v8i16 FPR128:$src))),
- (v8f16 (REV64v8i16 FPR128:$src))>;
def : Pat<(v8f16 (bitconvert (v16i8 FPR128:$src))),
(v8f16 (REV16v16i8 FPR128:$src))>;
def : Pat<(v8f16 (bitconvert (v2f64 FPR128:$src))),
@@ -6146,6 +6135,7 @@ def : Pat<(v8f16 (bitconvert (v2f64 FPR1
def : Pat<(v8f16 (bitconvert (v4f32 FPR128:$src))),
(v8f16 (REV32v8i16 FPR128:$src))>;
}
+def : Pat<(v8f16 (bitconvert (v8i16 FPR128:$src))), (v8f16 FPR128:$src)>;
let Predicates = [IsLE] in {
def : Pat<(v16i8 (bitconvert (f128 FPR128:$src))), (v16i8 FPR128:$src)>;
Modified: llvm/trunk/test/CodeGen/AArch64/arm64-big-endian-bitconverts.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-big-endian-bitconverts.ll?rev=322663&r1=322662&r2=322663&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64-big-endian-bitconverts.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/arm64-big-endian-bitconverts.ll Wed Jan 17 06:39:29 2018
@@ -51,6 +51,20 @@ define void @test_i64_v2i32(<2 x i32>* %
ret void
}
+; CHECK-LABEL: test_i64_v4f16:
+define void @test_i64_v4f16(<4 x half>* %p, i64* %q) {
+; CHECK: ld1 { v{{[0-9]+}}.2s }
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: rev64 v{{[0-9]+}}.4h
+; CHECK: str
+ %1 = load <4 x half>, <4 x half>* %p
+ %2 = fadd <4 x half> %1, %1
+ %3 = bitcast <4 x half> %2 to i64
+ %4 = add i64 %3, %3
+ store i64 %4, i64* %q
+ ret void
+}
+
; CHECK-LABEL: test_i64_v4i16:
define void @test_i64_v4i16(<4 x i16>* %p, i64* %q) {
; CHECK: ld1 { v{{[0-9]+}}.4h }
@@ -140,6 +154,20 @@ define void @test_f64_v4i16(<4 x i16>* %
ret void
}
+; CHECK-LABEL: test_f64_v4f16:
+define void @test_f64_v4f16(<4 x half>* %p, double* %q) {
+; CHECK: ld1 { v{{[0-9]+}}.2s }
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: rev64 v{{[0-9]+}}.4h
+; CHECK: str
+ %1 = load <4 x half>, <4 x half>* %p
+ %2 = fadd <4 x half> %1, %1
+ %3 = bitcast <4 x half> %2 to double
+ %4 = fadd double %3, %3
+ store double %4, double* %q
+ ret void
+}
+
; CHECK-LABEL: test_f64_v8i8:
define void @test_f64_v8i8(<8 x i8>* %p, double* %q) {
; CHECK: ld1 { v{{[0-9]+}}.8b }
@@ -203,6 +231,20 @@ define void @test_v1i64_v2i32(<2 x i32>*
ret void
}
+; CHECK-LABEL: test_v1i64_v4f16:
+define void @test_v1i64_v4f16(<4 x half>* %p, <1 x i64>* %q) {
+; CHECK: ld1 { v{{[0-9]+}}.2s }
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: rev64 v{{[0-9]+}}.4h
+; CHECK: str
+ %1 = load <4 x half>, <4 x half>* %p
+ %2 = fadd <4 x half> %1, %1
+ %3 = bitcast <4 x half> %2 to <1 x i64>
+ %4 = add <1 x i64> %3, %3
+ store <1 x i64> %4, <1 x i64>* %q
+ ret void
+}
+
; CHECK-LABEL: test_v1i64_v4i16:
define void @test_v1i64_v4i16(<4 x i16>* %p, <1 x i64>* %q) {
; CHECK: ld1 { v{{[0-9]+}}.4h }
@@ -293,6 +335,20 @@ define void @test_v2f32_v4i16(<4 x i16>*
ret void
}
+; CHECK-LABEL: test_v2f32_v4f16:
+define void @test_v2f32_v4f16(<4 x half>* %p, <2 x float>* %q) {
+; CHECK: ld1 { v{{[0-9]+}}.2s }
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: st1 { v{{[0-9]+}}.2s }
+ %1 = load <4 x half>, <4 x half>* %p
+ %2 = fadd <4 x half> %1, %1
+ %3 = bitcast <4 x half> %2 to <2 x float>
+ %4 = fadd <2 x float> %3, %3
+ store <2 x float> %4, <2 x float>* %q
+ ret void
+}
+
; CHECK-LABEL: test_v2f32_v8i8:
define void @test_v2f32_v8i8(<8 x i8>* %p, <2 x float>* %q) {
; CHECK: ld1 { v{{[0-9]+}}.8b }
@@ -448,6 +504,19 @@ define void @test_v4i16_v2i32(<2 x i32>*
ret void
}
+; CHECK-LABEL: test_v4i16_v4f16:
+define void @test_v4i16_v4f16(<4 x half>* %p, <4 x i16>* %q) {
+; CHECK: ld1 { v{{[0-9]+}}.2s }
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: st1 { v{{[0-9]+}}.4h }
+ %1 = load <4 x half>, <4 x half>* %p
+ %2 = fadd <4 x half> %1, %1
+ %3 = bitcast <4 x half> %2 to <4 x i16>
+ %4 = add <4 x i16> %3, %3
+ store <4 x i16> %4, <4 x i16>* %q
+ ret void
+}
+
; CHECK-LABEL: test_v4i16_v8i8:
define void @test_v4i16_v8i8(<8 x i8>* %p, <4 x i16>* %q) {
; CHECK: ld1 { v{{[0-9]+}}.8b }
@@ -461,6 +530,103 @@ define void @test_v4i16_v8i8(<8 x i8>* %
ret void
}
+; CHECK-LABEL: test_v4f16_i64:
+define void @test_v4f16_i64(i64* %p, <4 x half>* %q) {
+; CHECK: ldr
+; CHECK: rev64 v{{[0-9]+}}.4h
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: st1 { v{{[0-9]+}}.2s }
+ %1 = load i64, i64* %p
+ %2 = add i64 %1, %1
+ %3 = bitcast i64 %2 to <4 x half>
+ %4 = fadd <4 x half> %3, %3
+ store <4 x half> %4, <4 x half>* %q
+ ret void
+}
+
+; CHECK-LABEL: test_v4f16_f64:
+define void @test_v4f16_f64(double* %p, <4 x half>* %q) {
+; CHECK: ldr
+; CHECK: rev64 v{{[0-9]+}}.4h
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: st1 { v{{[0-9]+}}.2s }
+ %1 = load double, double* %p
+ %2 = fadd double %1, %1
+ %3 = bitcast double %2 to <4 x half>
+ %4 = fadd <4 x half> %3, %3
+ store <4 x half> %4, <4 x half>* %q
+ ret void
+}
+
+; CHECK-LABEL: test_v4f16_v1i64:
+define void @test_v4f16_v1i64(<1 x i64>* %p, <4 x half>* %q) {
+; CHECK: ldr
+; CHECK: rev64 v{{[0-9]+}}.4h
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: st1 { v{{[0-9]+}}.2s }
+ %1 = load <1 x i64>, <1 x i64>* %p
+ %2 = add <1 x i64> %1, %1
+ %3 = bitcast <1 x i64> %2 to <4 x half>
+ %4 = fadd <4 x half> %3, %3
+ store <4 x half> %4, <4 x half>* %q
+ ret void
+}
+
+; CHECK-LABEL: test_v4f16_v2f32:
+define void @test_v4f16_v2f32(<2 x float>* %p, <4 x half>* %q) {
+; CHECK: ld1 { v{{[0-9]+}}.2s }
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: st1 { v{{[0-9]+}}.2s }
+ %1 = load <2 x float>, <2 x float>* %p
+ %2 = fadd <2 x float> %1, %1
+ %3 = bitcast <2 x float> %2 to <4 x half>
+ %4 = fadd <4 x half> %3, %3
+ store <4 x half> %4, <4 x half>* %q
+ ret void
+}
+
+; CHECK-LABEL: test_v4f16_v2i32:
+define void @test_v4f16_v2i32(<2 x i32>* %p, <4 x half>* %q) {
+; CHECK: ld1 { v{{[0-9]+}}.2s }
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: st1 { v{{[0-9]+}}.2s }
+ %1 = load <2 x i32>, <2 x i32>* %p
+ %2 = add <2 x i32> %1, %1
+ %3 = bitcast <2 x i32> %2 to <4 x half>
+ %4 = fadd <4 x half> %3, %3
+ store <4 x half> %4, <4 x half>* %q
+ ret void
+}
+
+; CHECK-LABEL: test_v4f16_v4i16:
+define void @test_v4f16_v4i16(<4 x i16>* %p, <4 x half>* %q) {
+; CHECK: ld1 { v{{[0-9]+}}.4h }
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: st1 { v{{[0-9]+}}.2s }
+ %1 = load <4 x i16>, <4 x i16>* %p
+ %2 = add <4 x i16> %1, %1
+ %3 = bitcast <4 x i16> %2 to <4 x half>
+ %4 = fadd <4 x half> %3, %3
+ store <4 x half> %4, <4 x half>* %q
+ ret void
+}
+
+; CHECK-LABEL: test_v4f16_v8i8:
+define void @test_v4f16_v8i8(<8 x i8>* %p, <4 x half>* %q) {
+; CHECK: ld1 { v{{[0-9]+}}.8b }
+; CHECK: rev16 v{{[0-9]+}}.8b
+; CHECK: rev32 v{{[0-9]+}}.4h
+; CHECK: st1 { v{{[0-9]+}}.2s }
+ %1 = load <8 x i8>, <8 x i8>* %p
+ %2 = add <8 x i8> %1, %1
+ %3 = bitcast <8 x i8> %2 to <4 x half>
+ %4 = fadd <4 x half> %3, %3
+ store <4 x half> %4, <4 x half>* %q
+ ret void
+}
+
; CHECK-LABEL: test_v8i8_i64:
define void @test_v8i8_i64(i64* %p, <8 x i8>* %q) {
; CHECK: ldr
@@ -1007,6 +1173,19 @@ define void @test_v8i16_v4i32(<4 x i32>*
ret void
}
+; CHECK-LABEL: test_v8i16_v8f16:
+define void @test_v8i16_v8f16(<8 x half>* %p, <8 x i16>* %q) {
+; CHECK: ld1 { v{{[0-9]+}}.2d }
+; CHECK: rev64 v{{[0-9]+}}.8h
+; CHECK: st1 { v{{[0-9]+}}.8h }
+ %1 = load <8 x half>, <8 x half>* %p
+ %2 = fadd <8 x half> %1, %1
+ %3 = bitcast <8 x half> %2 to <8 x i16>
+ %4 = add <8 x i16> %3, %3
+ store <8 x i16> %4, <8 x i16>* %q
+ ret void
+}
+
; CHECK-LABEL: test_v8i16_v16i8:
define void @test_v8i16_v16i8(<16 x i8>* %p, <8 x i16>* %q) {
; CHECK: ld1 { v{{[0-9]+}}.16b }
@@ -1087,6 +1266,20 @@ define void @test_v16i8_v4i32(<4 x i32>*
ret void
}
+; CHECK-LABEL: test_v16i8_v8f16:
+define void @test_v16i8_v8f16(<8 x half>* %p, <16 x i8>* %q) {
+; CHECK: ld1 { v{{[0-9]+}}.2d }
+; CHECK: rev64 v{{[0-9]+}}.8h
+; CHECK: rev16 v{{[0-9]+}}.16b
+; CHECK: st1 { v{{[0-9]+}}.16b }
+ %1 = load <8 x half>, <8 x half>* %p
+ %2 = fadd <8 x half> %1, %1
+ %3 = bitcast <8 x half> %2 to <16 x i8>
+ %4 = add <16 x i8> %3, %3
+ store <16 x i8> %4, <16 x i8>* %q
+ ret void
+}
+
; CHECK-LABEL: test_v16i8_v8i16:
define void @test_v16i8_v8i16(<8 x i16>* %p, <16 x i8>* %q) {
; CHECK: ld1 { v{{[0-9]+}}.8h }
@@ -1099,3 +1292,17 @@ define void @test_v16i8_v8i16(<8 x i16>*
store <16 x i8> %4, <16 x i8>* %q
ret void
}
+
+; CHECK-LABEL: test_v4f16_struct:
+%struct.struct1 = type { half, half, half, half }
+define %struct.struct1 @test_v4f16_struct(%struct.struct1* %ret) {
+entry:
+; CHECK: ld1 { {{v[0-9]+}}.2s }
+; CHECK: rev32
+; CHECK-NOT; rev64
+ %0 = bitcast %struct.struct1* %ret to <4 x half>*
+ %1 = load <4 x half>, <4 x half>* %0, align 2
+ %2 = extractelement <4 x half> %1, i32 0
+ %.fca.0.insert = insertvalue %struct.struct1 undef, half %2, 0
+ ret %struct.struct1 %.fca.0.insert
+}
More information about the llvm-commits
mailing list