summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDiana Picus <diana.picus@linaro.org>2018-01-17 13:34:10 +0000
committerDiana Picus <diana.picus@linaro.org>2018-01-17 13:34:10 +0000
commit65ed364fac666fe132812adbcd23e8b53b14a526 (patch)
tree6378bf315c2b3ca1582c37fd371ba4a4d898b91f
parent4d0ff0c74d35e6c5bfc60c3864e8ac7655737f8f (diff)
downloadbcm5719-llvm-65ed364fac666fe132812adbcd23e8b53b14a526.tar.gz
bcm5719-llvm-65ed364fac666fe132812adbcd23e8b53b14a526.zip
[ARM GlobalISel] Legalize G_FPEXT and G_FPTRUNC
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. llvm-svn: 322651
-rw-r--r--llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp47
-rw-r--r--llvm/lib/Target/ARM/ARMLegalizerInfo.cpp12
-rw-r--r--llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir79
3 files changed, 138 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 200d6b8abec..f1cb5c0ad02 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -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();
diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
index 3e694b80f80..7b560088510 100644
--- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
@@ -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
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir
index 4b93610ab99..297eb6f28f6 100644
--- a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir
+++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir
@@ -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
OpenPOWER on IntegriCloud