[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