[PATCH] [X86][FastISel] Teach how to select float-half conversion intrinsics.

Andrea Di Biagio Andrea_DiBiagio at sn.scee.net
Mon Feb 16 08:46:43 PST 2015


Hi mkuper, ributzka, qcolombet,

This patch teaches X86FastISel how to select intrinsic 'convert_from_fp16' and intrinsic 'convert_to_fp16'.

If the target has F16C (and no -soft-float), we can select instruction VCVTPS2PHrr for a float-to-half conversion, and VCVTPH2PSrr for a half-to-float conversion.

Added test fast-isel-float-half-convertion.ll to check that fast-isel doesn't fail to select float-half conversions if the target has F16C.

Please let me know if ok to submit.

Thanks,
Andrea

http://reviews.llvm.org/D7673

Files:
  lib/Target/X86/X86FastISel.cpp
  test/CodeGen/X86/fast-isel-float-half-convertion.ll

Index: lib/Target/X86/X86FastISel.cpp
===================================================================
--- lib/Target/X86/X86FastISel.cpp
+++ lib/Target/X86/X86FastISel.cpp
@@ -2136,6 +2136,60 @@
   // FIXME: Handle more intrinsics.
   switch (II->getIntrinsicID()) {
   default: return false;
+  case Intrinsic::convert_from_fp16:
+  case Intrinsic::convert_to_fp16: {
+    if (TM.Options.UseSoftFloat || !Subtarget->hasF16C())
+      return false;
+
+    const Value *Op = II->getArgOperand(0);
+    bool IsFloatToHalf = II->getIntrinsicID() == Intrinsic::convert_to_fp16;
+    // F16C allows converting from float to half and from half to float.
+    // In the case of float-to-half conversion, the type must be a float.
+    if (IsFloatToHalf && !Op->getType()->isFloatTy())
+      return false;
+
+    unsigned InputReg = getRegForValue(Op);
+    if (!IsFloatToHalf) {
+      assert(Op->getType()->isIntegerTy(16) && "Expected a 16-bit integer!");
+      // Explicitly sign-extend the input value to 32-bit.
+      InputReg = fastEmit_r(MVT::i16, MVT::i32, ISD::SIGN_EXTEND,
+                            InputReg, /*Kill=*/false);
+    }
+
+    // Copy to a vector (VR128) register class.
+    const TargetRegisterClass *RC = TLI.getRegClassFor(MVT::v8i16);
+    unsigned ResultReg = createResultReg(RC);
+    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+            TII.get(TargetOpcode::COPY), ResultReg).addReg(InputReg);
+    InputReg = ResultReg;
+
+    // Now generate a VCVTPS2PHrr/VCVTPH2PSrr.
+    ResultReg = createResultReg(RC);
+    unsigned Opc = IsFloatToHalf ? X86::VCVTPS2PHrr : X86::VCVTPH2PSrr;
+    MachineInstrBuilder MIB;
+    MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
+                  ResultReg).addReg(InputReg, RegState::Kill);
+    if (IsFloatToHalf)
+      // Instruction VCVTPS2PHrr requires an extra immediate operand that
+      // provides rounding control.
+      MIB.addImm(0);
+    InputReg = ResultReg;
+
+    // Emit another copy to register class.
+    RC = IsFloatToHalf ? &X86::GR32RegClass : &X86::FR32RegClass;
+    ResultReg = createResultReg(RC);
+    MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+                  TII.get(TargetOpcode::COPY), ResultReg);
+    MIB.addReg(InputReg, RegState::Kill);
+
+    if (IsFloatToHalf)
+      // In the case of float-to-half conversions, the half float is in
+      // the lower 16-bits of ResultReg.
+      ResultReg = fastEmitInst_extractsubreg(MVT::i16, ResultReg, /*Kill=*/true,
+                                             X86::sub_16bit);
+    updateValueMap(II, ResultReg);
+    return true;
+  }
   case Intrinsic::frameaddress: {
     MachineFunction *MF = FuncInfo.MF;
     if (MF->getTarget().getMCAsmInfo()->usesWindowsCFI())
Index: test/CodeGen/X86/fast-isel-float-half-convertion.ll
===================================================================
--- test/CodeGen/X86/fast-isel-float-half-convertion.ll
+++ test/CodeGen/X86/fast-isel-float-half-convertion.ll
@@ -0,0 +1,21 @@
+; RUN: llc -O0 -fast-isel-abort -mtriple=x86_64-unknown-unknown -mattr=+f16c < %s | FileCheck %s
+
+define i16 @test_fp32_to_fp16(float %a) {
+; CHECK-LABEL: test_fp32_to_fp16:
+; CHECK: vcvtps2ph
+entry:
+  %0 = call i16 @llvm.convert.to.fp16.f32(float %a)
+  ret i16 %0
+}
+
+define float @test_fp16_to_fp32(i16 signext %a) {
+; CHECK-LABEL: test_fp16_to_fp32:
+; CHECK: vcvtph2ps
+entry:
+  %0 = call float @llvm.convert.from.fp16.f32(i16 %a)
+  ret float %0
+}
+
+
+declare i16 @llvm.convert.to.fp16.f32(float)
+declare float @llvm.convert.from.fp16.f32(i16)

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D7673.20036.patch
Type: text/x-patch
Size: 3596 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150216/58782850/attachment.bin>


More information about the llvm-commits mailing list