[AArch64] Handle vec4, vec8, vec16 *itofp for half
authorPirama Arumuga Nainar <pirama@google.com>
Thu, 23 Apr 2015 17:16:27 +0000 (17:16 +0000)
committerPirama Arumuga Nainar <pirama@google.com>
Thu, 23 Apr 2015 17:16:27 +0000 (17:16 +0000)
Summary:
Set operation action for SINT_TO_FP and UINT_TO_FP nodes with v4i32,
v8i8, v8i16 inputs to allow promotion of v4f16 results.

Add tests for sitofp and uitofp for vec4, vec8, vec16, and i8, i16, i32,
and i64 vectors.  Only missing tests are for v16i8 and v16i16 as the
shift operations are too complicated to write a proper check sequence.

The conversions from v4i64 to v4f16 do not depend on this patch - v4i64
is split and the conversion gets handled while lowering v2i64.  I am
adding a test here for completeness.

Reviewers: aemerson, rengolin, ab, jmolloy, srhines

Subscribers: rengolin, aemerson, llvm-commits

Differential Revision: http://reviews.llvm.org/D9166

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

lib/Target/AArch64/AArch64ISelLowering.cpp
test/CodeGen/AArch64/fp16-v16-instructions.ll [new file with mode: 0644]
test/CodeGen/AArch64/fp16-v4-instructions.ll
test/CodeGen/AArch64/fp16-v8-instructions.ll

index 3dc236a89da34172518587d541c57ed8f43998f1..0607c4a3b9119ad3b22ecb962f3e00307a2dd82d 100644 (file)
@@ -557,11 +557,21 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::SINT_TO_FP, MVT::v4i8, Promote);
     setOperationAction(ISD::UINT_TO_FP, MVT::v4i16, Promote);
     setOperationAction(ISD::SINT_TO_FP, MVT::v4i16, Promote);
+    // i8 and i16 vector elements also need promotion to i32 for v8i8 or v8i16
+    // -> v8f16 conversions.
+    setOperationAction(ISD::SINT_TO_FP, MVT::v8i8, Promote);
+    setOperationAction(ISD::UINT_TO_FP, MVT::v8i8, Promote);
+    setOperationAction(ISD::SINT_TO_FP, MVT::v8i16, Promote);
+    setOperationAction(ISD::UINT_TO_FP, MVT::v8i16, Promote);
     // Similarly, there is no direct i32 -> f64 vector conversion instruction.
     setOperationAction(ISD::SINT_TO_FP, MVT::v2i32, Custom);
     setOperationAction(ISD::UINT_TO_FP, MVT::v2i32, Custom);
     setOperationAction(ISD::SINT_TO_FP, MVT::v2i64, Custom);
     setOperationAction(ISD::UINT_TO_FP, MVT::v2i64, Custom);
+    // Or, direct i32 -> f16 vector conversion.  Set it so custom, so the
+    // conversion happens in two steps: v4i32 -> v4f32 -> v4f16
+    setOperationAction(ISD::SINT_TO_FP, MVT::v4i32, Custom);
+    setOperationAction(ISD::UINT_TO_FP, MVT::v4i32, Custom);
 
     // AArch64 doesn't have MUL.2d:
     setOperationAction(ISD::MUL, MVT::v2i64, Expand);
diff --git a/test/CodeGen/AArch64/fp16-v16-instructions.ll b/test/CodeGen/AArch64/fp16-v16-instructions.ll
new file mode 100644 (file)
index 0000000..1af2bd1
--- /dev/null
@@ -0,0 +1,105 @@
+; RUN: llc < %s -mtriple=aarch64-none-eabi | FileCheck %s
+
+
+define <16 x half> @sitofp_i32(<16 x i32> %a) #0 {
+; CHECK-LABEL: sitofp_i32:
+; CHECK-DAG: scvtf [[S0:v[0-9]+\.4s]], v0.4s
+; CHECK-DAG: scvtf [[S1:v[0-9]+\.4s]], v1.4s
+; CHECK-DAG: scvtf [[S2:v[0-9]+\.4s]], v2.4s
+; CHECK-DAG: scvtf [[S3:v[0-9]+\.4s]], v3.4s
+; CHECK-DAG: fcvtn v0.4h, [[S0]]
+; CHECK-DAG: fcvtn v1.4h, [[S2]]
+; CHECK-DAG: v[[R1:[0-9]+]].4h, [[S1]]
+; CHECK-DAG: v[[R3:[0-9]+]].4h, [[S3]]
+; CHECK-DAg: ins v0.d[1], v[[R1]].d[0]
+; CHECK-DAG: ins v1.d[1], v[[R3]].d[0]
+
+  %1 = sitofp <16 x i32> %a to <16 x half>
+  ret <16 x half> %1
+}
+
+
+define <16 x half> @sitofp_i64(<16 x i64> %a) #0 {
+; CHECK-LABEL: sitofp_i64:
+; CHECK-DAG: scvtf [[D0:v[0-9]+\.2d]], v0.2d
+; CHECK-DAG: scvtf [[D1:v[0-9]+\.2d]], v1.2d
+; CHECK-DAG: scvtf [[D2:v[0-9]+\.2d]], v2.2d
+; CHECK-DAG: scvtf [[D3:v[0-9]+\.2d]], v3.2d
+; CHECK-DAG: scvtf [[D4:v[0-9]+\.2d]], v4.2d
+; CHECK-DAG: scvtf [[D5:v[0-9]+\.2d]], v5.2d
+; CHECK-DAG: scvtf [[D6:v[0-9]+\.2d]], v6.2d
+; CHECK-DAG: scvtf [[D7:v[0-9]+\.2d]], v7.2d
+
+; CHECK-DAG: fcvtn [[S0:v[0-9]+]].2s, [[D0]]
+; CHECK-DAG: fcvtn [[S1:v[0-9]+]].2s, [[D2]]
+; CHECK-DAG: fcvtn [[S2:v[0-9]+]].2s, [[D4]]
+; CHECK-DAG: fcvtn [[S3:v[0-9]+]].2s, [[D6]]
+
+; CHECK-DAG: fcvtn2 [[S0]].4s, [[D1]]
+; CHECK-DAG: fcvtn2 [[S1]].4s, [[D3]]
+; CHECK-DAG: fcvtn2 [[S2]].4s, [[D5]]
+; CHECK-DAG: fcvtn2 [[S3]].4s, [[D7]]
+
+; CHECK-DAG: fcvtn v0.4h, [[S0]].4s
+; CHECK-DAG: fcvtn v1.4h, [[S2]].4s
+; CHECK-DAG: fcvtn v[[R1:[0-9]+]].4h, [[S1]].4s
+; CHECK-DAG: fcvtn v[[R3:[0-9]+]].4h, [[S3]].4s
+; CHECK-DAG: ins v0.d[1], v[[R1]].d[0]
+; CHECK-DAG: ins v1.d[1], v[[R3]].d[0]
+
+  %1 = sitofp <16 x i64> %a to <16 x half>
+  ret <16 x half> %1
+}
+
+
+define <16 x half> @uitofp_i32(<16 x i32> %a) #0 {
+; CHECK-LABEL: uitofp_i32:
+; CHECK-DAG: ucvtf [[S0:v[0-9]+\.4s]], v0.4s
+; CHECK-DAG: ucvtf [[S1:v[0-9]+\.4s]], v1.4s
+; CHECK-DAG: ucvtf [[S2:v[0-9]+\.4s]], v2.4s
+; CHECK-DAG: ucvtf [[S3:v[0-9]+\.4s]], v3.4s
+; CHECK-DAG: fcvtn v0.4h, [[S0]]
+; CHECK-DAG: fcvtn v1.4h, [[S2]]
+; CHECK-DAG: v[[R1:[0-9]+]].4h, [[S1]]
+; CHECK-DAG: v[[R3:[0-9]+]].4h, [[S3]]
+; CHECK-DAg: ins v0.d[1], v[[R1]].d[0]
+; CHECK-DAG: ins v1.d[1], v[[R3]].d[0]
+
+  %1 = uitofp <16 x i32> %a to <16 x half>
+  ret <16 x half> %1
+}
+
+
+define <16 x half> @uitofp_i64(<16 x i64> %a) #0 {
+; CHECK-LABEL: uitofp_i64:
+; CHECK-DAG: ucvtf [[D0:v[0-9]+\.2d]], v0.2d
+; CHECK-DAG: ucvtf [[D1:v[0-9]+\.2d]], v1.2d
+; CHECK-DAG: ucvtf [[D2:v[0-9]+\.2d]], v2.2d
+; CHECK-DAG: ucvtf [[D3:v[0-9]+\.2d]], v3.2d
+; CHECK-DAG: ucvtf [[D4:v[0-9]+\.2d]], v4.2d
+; CHECK-DAG: ucvtf [[D5:v[0-9]+\.2d]], v5.2d
+; CHECK-DAG: ucvtf [[D6:v[0-9]+\.2d]], v6.2d
+; CHECK-DAG: ucvtf [[D7:v[0-9]+\.2d]], v7.2d
+
+; CHECK-DAG: fcvtn [[S0:v[0-9]+]].2s, [[D0]]
+; CHECK-DAG: fcvtn [[S1:v[0-9]+]].2s, [[D2]]
+; CHECK-DAG: fcvtn [[S2:v[0-9]+]].2s, [[D4]]
+; CHECK-DAG: fcvtn [[S3:v[0-9]+]].2s, [[D6]]
+
+; CHECK-DAG: fcvtn2 [[S0]].4s, [[D1]]
+; CHECK-DAG: fcvtn2 [[S1]].4s, [[D3]]
+; CHECK-DAG: fcvtn2 [[S2]].4s, [[D5]]
+; CHECK-DAG: fcvtn2 [[S3]].4s, [[D7]]
+
+; CHECK-DAG: fcvtn v0.4h, [[S0]].4s
+; CHECK-DAG: fcvtn v1.4h, [[S2]].4s
+; CHECK-DAG: fcvtn v[[R1:[0-9]+]].4h, [[S1]].4s
+; CHECK-DAG: fcvtn v[[R3:[0-9]+]].4h, [[S3]].4s
+; CHECK-DAG: ins v0.d[1], v[[R1]].d[0]
+; CHECK-DAG: ins v1.d[1], v[[R3]].d[0]
+
+  %1 = uitofp <16 x i64> %a to <16 x half>
+  ret <16 x half> %1
+}
+
+attributes #0 = { nounwind }
index 6db4e9745dac5edf62cc80ce8cdb8af6e3c48688..0dbda152fca91d1a9942f97567a36066ffa9821f 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llc < %s -mtriple=aarch64-none-eabi | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -mtriple=aarch64-none-eabi | FileCheck %s
 
 define <4 x half> @add_h(<4 x half> %a, <4 x half> %b) {
 entry:
@@ -129,3 +129,93 @@ define <4 x i16> @bitcast_h_to_i(float, <4 x half> %a) {
   %2 = bitcast <4 x half> %a to <4 x i16>
   ret <4 x i16> %2
 }
+
+
+define <4 x half> @sitofp_i8(<4 x i8> %a) #0 {
+; CHECK-LABEL: sitofp_i8:
+; CHECK-NEXT: shl [[OP1:v[0-9]+\.4h]], v0.4h, #8
+; CHECK-NEXT: sshr [[OP2:v[0-9]+\.4h]], [[OP1]], #8
+; CHECK-NEXT: sshll [[OP3:v[0-9]+\.4s]], [[OP2]], #0
+; CHECK-NEXT: scvtf [[OP4:v[0-9]+\.4s]], [[OP3]]
+; CHECK-NEXT: fcvtn v0.4h, [[OP4]]
+; CHECK-NEXT: ret
+  %1 = sitofp <4 x i8> %a to <4 x half>
+  ret <4 x half> %1
+}
+
+
+define <4 x half> @sitofp_i16(<4 x i16> %a) #0 {
+; CHECK-LABEL: sitofp_i16:
+; CHECK-NEXT: sshll [[OP1:v[0-9]+\.4s]], v0.4h, #0
+; CHECK-NEXT: scvtf [[OP2:v[0-9]+\.4s]], [[OP1]]
+; CHECK-NEXT: fcvtn v0.4h, [[OP2]]
+; CHECK-NEXT: ret
+  %1 = sitofp <4 x i16> %a to <4 x half>
+  ret <4 x half> %1
+}
+
+
+define <4 x half> @sitofp_i32(<4 x i32> %a) #0 {
+; CHECK-LABEL: sitofp_i32:
+; CHECK-NEXT: scvtf [[OP1:v[0-9]+\.4s]], v0.4s
+; CHECK-NEXT: fcvtn v0.4h, [[OP1]]
+  %1 = sitofp <4 x i32> %a to <4 x half>
+  ret <4 x half> %1
+}
+
+
+define <4 x half> @sitofp_i64(<4 x i64> %a) #0 {
+; CHECK-LABEL: sitofp_i64:
+; CHECK-DAG: scvtf [[OP1:v[0-9]+\.2d]], v0.2d
+; CHECK-DAG: scvtf [[OP2:v[0-9]+\.2d]], v1.2d
+; CHECK-DAG: fcvtn [[OP3:v[0-9]+]].2s, [[OP1]]
+; CHECK-NEXT: fcvtn2 [[OP3]].4s, [[OP2]]
+; CHECK-NEXT: fcvtn v0.4h, [[OP3]].4s
+  %1 = sitofp <4 x i64> %a to <4 x half>
+  ret <4 x half> %1
+}
+
+define <4 x half> @uitofp_i8(<4 x i8> %a) #0 {
+; CHECK-LABEL: uitofp_i8:
+; CHECK-NEXT: bic v0.4h, #0xff, lsl #8
+; CHECK-NEXT: ushll [[OP1:v[0-9]+\.4s]], v0.4h, #0
+; CHECK-NEXT: ucvtf [[OP2:v[0-9]+\.4s]], [[OP1]]
+; CHECK-NEXT: fcvtn v0.4h, [[OP2]]
+; CHECK-NEXT: ret
+  %1 = uitofp <4 x i8> %a to <4 x half>
+  ret <4 x half> %1
+}
+
+
+define <4 x half> @uitofp_i16(<4 x i16> %a) #0 {
+; CHECK-LABEL: uitofp_i16:
+; CHECK-NEXT: ushll [[OP1:v[0-9]+\.4s]], v0.4h, #0
+; CHECK-NEXT: ucvtf [[OP2:v[0-9]+\.4s]], [[OP1]]
+; CHECK-NEXT: fcvtn v0.4h, [[OP2]]
+; CHECK-NEXT: ret
+  %1 = uitofp <4 x i16> %a to <4 x half>
+  ret <4 x half> %1
+}
+
+
+define <4 x half> @uitofp_i32(<4 x i32> %a) #0 {
+; CHECK-LABEL: uitofp_i32:
+; CHECK-NEXT: ucvtf [[OP1:v[0-9]+\.4s]], v0.4s
+; CHECK-NEXT: fcvtn v0.4h, [[OP1]]
+  %1 = uitofp <4 x i32> %a to <4 x half>
+  ret <4 x half> %1
+}
+
+
+define <4 x half> @uitofp_i64(<4 x i64> %a) #0 {
+; CHECK-LABEL: uitofp_i64:
+; CHECK-DAG: ucvtf [[OP1:v[0-9]+\.2d]], v0.2d
+; CHECK-DAG: ucvtf [[OP2:v[0-9]+\.2d]], v1.2d
+; CHECK-DAG: fcvtn [[OP3:v[0-9]+]].2s, [[OP1]]
+; CHECK-NEXT: fcvtn2 [[OP3]].4s, [[OP2]]
+; CHECK-NEXT: fcvtn v0.4h, [[OP3]].4s
+  %1 = uitofp <4 x i64> %a to <4 x half>
+  ret <4 x half> %1
+}
+
+attributes #0 = { nounwind }
index e51c0c5f504a0ec74b2a64eafafca4c2c5cd5314..10a8c22d6f7efde6b30e0a21646c3a122ab109a4 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llc < %s -mtriple=aarch64-none-eabi | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -mtriple=aarch64-none-eabi | FileCheck %s
 
 define <8 x half> @add_h(<8 x half> %a, <8 x half> %b) {
 entry:
@@ -253,3 +253,109 @@ define <8 x i16> @bitcast_h_to_i(float, <8 x half> %a) {
   ret <8 x i16> %2
 }
 
+
+define <8 x half> @sitofp_i8(<8 x i8> %a) #0 {
+; CHECK-LABEL: sitofp_i8:
+; CHECK-NEXT: sshll v[[REG1:[0-9]+]].8h, v0.8b, #0
+; CHECK-NEXT: sshll2 [[LO:v[0-9]+\.4s]], v[[REG1]].8h, #0
+; CHECK-NEXT: sshll  [[HI:v[0-9]+\.4s]], v[[REG1]].4h, #0
+; CHECK-DAG: scvtf [[HIF:v[0-9]+\.4s]], [[HI]]
+; CHECK-DAG: scvtf [[LOF:v[0-9]+\.4s]], [[LO]]
+; CHECK-DAG: fcvtn v[[LOREG:[0-9]+]].4h, [[LOF]]
+; CHECK-DAG: fcvtn v0.4h, [[HIF]]
+; CHECK: ins v0.d[1], v[[LOREG]].d[0]
+  %1 = sitofp <8 x i8> %a to <8 x half>
+  ret <8 x half> %1
+}
+
+
+define <8 x half> @sitofp_i16(<8 x i16> %a) #0 {
+; CHECK-LABEL: sitofp_i16:
+; CHECK-NEXT: sshll2 [[LO:v[0-9]+\.4s]], v0.8h, #0
+; CHECK-NEXT: sshll  [[HI:v[0-9]+\.4s]], v0.4h, #0
+; CHECK-DAG: scvtf [[HIF:v[0-9]+\.4s]], [[HI]]
+; CHECK-DAG: scvtf [[LOF:v[0-9]+\.4s]], [[LO]]
+; CHECK-DAG: fcvtn v[[LOREG:[0-9]+]].4h, [[LOF]]
+; CHECK-DAG: fcvtn v0.4h, [[HIF]]
+; CHECK: ins v0.d[1], v[[LOREG]].d[0]
+  %1 = sitofp <8 x i16> %a to <8 x half>
+  ret <8 x half> %1
+}
+
+
+define <8 x half> @sitofp_i32(<8 x i32> %a) #0 {
+; CHECK-LABEL: sitofp_i32:
+; CHECK-DAG: scvtf [[OP1:v[0-9]+\.4s]], v0.4s
+; CHECK-DAG: scvtf [[OP2:v[0-9]+\.4s]], v1.4s
+; CHECK-DAG: fcvtn v[[REG:[0-9]+]].4h, [[OP2]]
+; CHECK-DAG: fcvtn v0.4h, [[OP1]]
+; CHECK: ins v0.d[1], v[[REG]].d[0]
+  %1 = sitofp <8 x i32> %a to <8 x half>
+  ret <8 x half> %1
+}
+
+
+define <8 x half> @sitofp_i64(<8 x i64> %a) #0 {
+; CHECK-LABEL: sitofp_i64:
+; CHECK-DAG: scvtf [[OP1:v[0-9]+\.2d]], v0.2d
+; CHECK-DAG: scvtf [[OP2:v[0-9]+\.2d]], v1.2d
+; CHECK-DAG: fcvtn [[OP3:v[0-9]+]].2s, [[OP1]]
+; CHECK-DAG: fcvtn2 [[OP3]].4s, [[OP2]]
+; CHECK: fcvtn v0.4h, [[OP3]].4s
+  %1 = sitofp <8 x i64> %a to <8 x half>
+  ret <8 x half> %1
+}
+
+define <8 x half> @uitofp_i8(<8 x i8> %a) #0 {
+; CHECK-LABEL: uitofp_i8:
+; CHECK-NEXT: ushll v[[REG1:[0-9]+]].8h, v0.8b, #0
+; CHECK-NEXT: ushll2 [[LO:v[0-9]+\.4s]], v[[REG1]].8h, #0
+; CHECK-NEXT: ushll  [[HI:v[0-9]+\.4s]], v[[REG1]].4h, #0
+; CHECK-DAG: ucvtf [[HIF:v[0-9]+\.4s]], [[HI]]
+; CHECK-DAG: ucvtf [[LOF:v[0-9]+\.4s]], [[LO]]
+; CHECK-DAG: fcvtn v[[LOREG:[0-9]+]].4h, [[LOF]]
+; CHECK-DAG: fcvtn v0.4h, [[HIF]]
+; CHECK: ins v0.d[1], v[[LOREG]].d[0]
+  %1 = uitofp <8 x i8> %a to <8 x half>
+  ret <8 x half> %1
+}
+
+
+define <8 x half> @uitofp_i16(<8 x i16> %a) #0 {
+; CHECK-LABEL: uitofp_i16:
+; CHECK-NEXT: ushll2 [[LO:v[0-9]+\.4s]], v0.8h, #0
+; CHECK-NEXT: ushll  [[HI:v[0-9]+\.4s]], v0.4h, #0
+; CHECK-DAG: ucvtf [[HIF:v[0-9]+\.4s]], [[HI]]
+; CHECK-DAG: ucvtf [[LOF:v[0-9]+\.4s]], [[LO]]
+; CHECK-DAG: fcvtn v[[LOREG:[0-9]+]].4h, [[LOF]]
+; CHECK-DAG: fcvtn v0.4h, [[HIF]]
+; CHECK: ins v0.d[1], v[[LOREG]].d[0]
+  %1 = uitofp <8 x i16> %a to <8 x half>
+  ret <8 x half> %1
+}
+
+
+define <8 x half> @uitofp_i32(<8 x i32> %a) #0 {
+; CHECK-LABEL: uitofp_i32:
+; CHECK-DAG: ucvtf [[OP1:v[0-9]+\.4s]], v0.4s
+; CHECK-DAG: ucvtf [[OP2:v[0-9]+\.4s]], v1.4s
+; CHECK-DAG: fcvtn v[[REG:[0-9]+]].4h, [[OP2]]
+; CHECK-DAG: fcvtn v0.4h, [[OP1]]
+; CHECK: ins v0.d[1], v[[REG]].d[0]
+  %1 = uitofp <8 x i32> %a to <8 x half>
+  ret <8 x half> %1
+}
+
+
+define <8 x half> @uitofp_i64(<8 x i64> %a) #0 {
+; CHECK-LABEL: uitofp_i64:
+; CHECK-DAG: ucvtf [[OP1:v[0-9]+\.2d]], v0.2d
+; CHECK-DAG: ucvtf [[OP2:v[0-9]+\.2d]], v1.2d
+; CHECK-DAG: fcvtn [[OP3:v[0-9]+]].2s, [[OP1]]
+; CHECK-DAG: fcvtn2 [[OP3]].4s, [[OP2]]
+; CHECK: fcvtn v0.4h, [[OP3]].4s
+  %1 = uitofp <8 x i64> %a to <8 x half>
+  ret <8 x half> %1
+}
+
+attributes #0 = { nounwind }