OSDN Git Service

[ARM GlobalISel] Legalize G_FPEXT and G_FPTRUNC
authorDiana Picus <diana.picus@linaro.org>
Wed, 17 Jan 2018 13:34:10 +0000 (13:34 +0000)
committerDiana Picus <diana.picus@linaro.org>
Wed, 17 Jan 2018 13:34:10 +0000 (13:34 +0000)
Mark G_FPEXT and G_FPTRUNC as legal or libcall, depending on hardware
support, but only for conversions between float and double.

Also add the necessary boilerplate so that the LegalizerHelper can
introduce the required libcalls. This also works only for float and
double, but isn't too difficult to extend when the need arises.

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

lib/CodeGen/GlobalISel/LegalizerHelper.cpp
lib/Target/ARM/ARMLegalizerInfo.cpp
test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir

index 200d6b8..f1cb5c0 100644 (file)
@@ -126,6 +126,7 @@ llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
   return LegalizerHelper::Legalized;
 }
 
+// Useful for libcalls where all operands have the same type.
 static LegalizerHelper::LegalizeResult
 simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
               Type *OpType) {
@@ -138,6 +139,28 @@ simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
                        Args);
 }
 
+static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
+                                       Type *FromType) {
+  auto ToMVT = MVT::getVT(ToType);
+  auto FromMVT = MVT::getVT(FromType);
+
+  switch (Opcode) {
+  case TargetOpcode::G_FPEXT:
+    return RTLIB::getFPEXT(FromMVT, ToMVT);
+  case TargetOpcode::G_FPTRUNC:
+    return RTLIB::getFPROUND(FromMVT, ToMVT);
+  }
+  llvm_unreachable("Unsupported libcall function");
+}
+
+static LegalizerHelper::LegalizeResult
+conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
+                  Type *FromType) {
+  RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
+  return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
+                       {{MI.getOperand(1).getReg(), FromType}});
+}
+
 LegalizerHelper::LegalizeResult
 LegalizerHelper::libcall(MachineInstr &MI) {
   LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
@@ -172,6 +195,30 @@ LegalizerHelper::libcall(MachineInstr &MI) {
       return Status;
     break;
   }
+  case TargetOpcode::G_FPEXT: {
+    // FIXME: Support other floating point types (half, fp128 etc)
+    unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
+    unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
+    if (ToSize != 64 || FromSize != 32)
+      return UnableToLegalize;
+    LegalizeResult Status = conversionLibcall(
+        MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
+    if (Status != Legalized)
+      return Status;
+    break;
+  }
+  case TargetOpcode::G_FPTRUNC: {
+    // FIXME: Support other floating point types (half, fp128 etc)
+    unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
+    unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
+    if (ToSize != 32 || FromSize != 64)
+      return UnableToLegalize;
+    LegalizeResult Status = conversionLibcall(
+        MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
+    if (Status != Legalized)
+      return Status;
+    break;
+  }
   }
 
   MI.eraseFromParent();
index 3e694b8..7b56008 100644 (file)
@@ -178,6 +178,12 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
     setAction({G_MERGE_VALUES, 1, s32}, Legal);
     setAction({G_UNMERGE_VALUES, s32}, Legal);
     setAction({G_UNMERGE_VALUES, 1, s64}, Legal);
+
+    setAction({G_FPEXT, s64}, Legal);
+    setAction({G_FPEXT, 1, s32}, Legal);
+
+    setAction({G_FPTRUNC, s32}, Legal);
+    setAction({G_FPTRUNC, 1, s64}, Legal);
   } else {
     for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
       for (auto Ty : {s32, s64})
@@ -192,6 +198,12 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
     setAction({G_FCMP, 1, s32}, Custom);
     setAction({G_FCMP, 1, s64}, Custom);
 
+    setAction({G_FPEXT, s64}, Legal);
+    setAction({G_FPEXT, 1, s32}, Libcall);
+
+    setAction({G_FPTRUNC, s32}, Legal);
+    setAction({G_FPTRUNC, 1, s64}, Libcall);
+
     if (AEABI(ST))
       setFCmpLibcallsAEABI();
     else
index 4b93610..297eb6f 100644 (file)
@@ -26,6 +26,9 @@
   define void @test_fneg_float() { ret void }
   define void @test_fneg_double() { ret void }
 
+  define void @test_fpext_float_to_double() { ret void }
+  define void @test_fptrunc_double_to_float() { ret void }
+
   define void @test_fcmp_true_s32() { ret void }
   define void @test_fcmp_false_s32() { ret void }
 
@@ -734,6 +737,82 @@ body:             |
     BX_RET 14, %noreg, implicit %r0, implicit %r1
 ...
 ---
+name:            test_fpext_float_to_double
+# CHECK-LABEL: name: test_fpext_float_to_double
+legalized:       false
+# CHECK: legalized: true
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+  - { id: 3, class: _ }
+body:             |
+  bb.0:
+    liveins: %r0
+
+    ; CHECK-DAG: [[X:%[0-9]+]]:_(s32) = COPY %r0
+    %0(s32) = COPY %r0
+    ; HARD: [[R:%[0-9]+]]:_(s64) = G_FPEXT [[X]]
+    ; SOFT-NOT: G_FPEXT
+    ; SOFT: ADJCALLSTACKDOWN
+    ; SOFT-DAG: %r0 = COPY [[X]]
+    ; SOFT-AEABI: BL &__aeabi_f2d, {{.*}}, implicit %r0, implicit-def %r0, implicit-def %r1
+    ; SOFT-DEFAULT: BL &__extendsfdf2, {{.*}}, implicit %r0, implicit-def %r0, implicit-def %r1
+    ; SOFT: [[R0:%[0-9]+]]:_(s32) = COPY %r0
+    ; SOFT: [[R1:%[0-9]+]]:_(s32) = COPY %r1
+    ; SOFT: ADJCALLSTACKUP
+    ; SOFT-NOT: G_FPEXT
+    %1(s64) = G_FPEXT %0(s32)
+    ; HARD: G_UNMERGE_VALUES [[R]](s64)
+    ; SOFT-DAG: %r{{[0-1]}} = COPY [[R0]]
+    ; SOFT-DAG: %r{{[0-1]}} = COPY [[R1]]
+    %2(s32), %3(s32) = G_UNMERGE_VALUES %1(s64)
+    %r0 = COPY %2(s32)
+    %r1 = COPY %3(s32)
+    BX_RET 14, %noreg, implicit %r0, implicit %r1
+...
+---
+name:            test_fptrunc_double_to_float
+# CHECK-LABEL: name: test_fptrunc_double_to_float
+legalized:       false
+# CHECK: legalized: true
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+  - { id: 3, class: _ }
+body:             |
+  bb.0:
+    liveins: %r0, %r1
+
+    ; CHECK-DAG: [[X0:%[0-9]+]]:_(s32) = COPY %r0
+    ; CHECK-DAG: [[X1:%[0-9]+]]:_(s32) = COPY %r1
+    ; HARD: [[X:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[X0]]
+    %0(s32) = COPY %r0
+    %1(s32) = COPY %r1
+    %2(s64) = G_MERGE_VALUES %0(s32), %1(s32)
+    ; HARD: [[R:%[0-9]+]]:_(s32) = G_FPTRUNC [[X]]
+    ; SOFT-NOT: G_FPTRUNC
+    ; SOFT: ADJCALLSTACKDOWN
+    ; SOFT-DAG: %r0 = COPY [[X0]]
+    ; SOFT-DAG: %r1 = COPY [[X1]]
+    ; SOFT-AEABI: BL &__aeabi_d2f, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
+    ; SOFT-DEFAULT: BL &__truncdfsf2, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
+    ; SOFT: [[R:%[0-9]+]]:_(s32) = COPY %r0
+    ; SOFT: ADJCALLSTACKUP
+    ; SOFT-NOT: G_FPTRUNC
+    %3(s32) = G_FPTRUNC %2(s64)
+    ; CHECK: %r0 = COPY [[R]]
+    %r0 = COPY %3(s32)
+    BX_RET 14, %noreg, implicit %r0
+---
+...
 name:            test_fcmp_true_s32
 # CHECK-LABEL: name: test_fcmp_true_s32
 legalized:       false