diff options
| author | Diana Picus <diana.picus@linaro.org> | 2018-01-17 13:34:10 +0000 |
|---|---|---|
| committer | Diana Picus <diana.picus@linaro.org> | 2018-01-17 13:34:10 +0000 |
| commit | 65ed364fac666fe132812adbcd23e8b53b14a526 (patch) | |
| tree | 6378bf315c2b3ca1582c37fd371ba4a4d898b91f | |
| parent | 4d0ff0c74d35e6c5bfc60c3864e8ac7655737f8f (diff) | |
| download | bcm5719-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.cpp | 47 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMLegalizerInfo.cpp | 12 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir | 79 |
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 |

