diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp index ea2196a584127..7ee54c5932b15 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -444,7 +444,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) // Regardless of FP16 support, widen 16-bit elements to 32-bits. .minScalar(0, s32) .libcallFor({s32, s64, s128}); - getActionDefinitionsBuilder(G_FPOWI) + getActionDefinitionsBuilder({G_FPOWI, G_FLDEXP}) .scalarize(0) .minScalar(0, s32) .libcallFor({{s32, s32}, {s64, s32}, {s128, s32}}); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir index 040f97f96ee21..da8cd4f437b6e 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -540,8 +540,9 @@ # DEBUG-NEXT: .. the first uncovered type index: 1, OK # DEBUG-NEXT: .. the first uncovered imm index: 0, OK # DEBUG-NEXT: G_FLDEXP (opcode {{[0-9]+}}): 2 type indices, 0 imm indices -# DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined -# DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}} +# DEBUG-NEXT: .. the first uncovered type index: 2, OK +# DEBUG-NEXT: .. the first uncovered imm index: 0, OK # DEBUG-NEXT: G_FFREXP (opcode {{[0-9]+}}): 2 type indices, 0 imm indices # DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined # DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined diff --git a/llvm/test/CodeGen/AArch64/ldexp.ll b/llvm/test/CodeGen/AArch64/ldexp.ll index 6019fa1490e3d..1e35bd627a199 100644 --- a/llvm/test/CodeGen/AArch64/ldexp.ll +++ b/llvm/test/CodeGen/AArch64/ldexp.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 ; RUN: llc -mtriple=aarch64 -mattr=+sve < %s -o - | FileCheck -check-prefixes=SVE,SVELINUX %s +; RUN: llc -mtriple=aarch64 -global-isel < %s -o - | FileCheck -check-prefixes=GISEL %s ; RUN: llc -mtriple=aarch64-windows-msvc -mattr=+sve < %s -o - | FileCheck -check-prefixes=SVE,SVEWINDOWS %s ; RUN: llc -mtriple=aarch64-windows-msvc < %s -o - | FileCheck -check-prefixes=WINDOWS %s @@ -15,6 +16,10 @@ define double @testExp(double %val, i32 %a) { ; SVE-NEXT: // kill: def $d0 killed $d0 killed $z0 ; SVE-NEXT: ret ; +; GISEL-LABEL: testExp: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: b ldexp +; ; WINDOWS-LABEL: testExp: ; WINDOWS: // %bb.0: // %entry ; WINDOWS-NEXT: b ldexp @@ -37,6 +42,10 @@ define double @testExpIntrinsic(double %val, i32 %a) { ; SVE-NEXT: // kill: def $d0 killed $d0 killed $z0 ; SVE-NEXT: ret ; +; GISEL-LABEL: testExpIntrinsic: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: b ldexp +; ; WINDOWS-LABEL: testExpIntrinsic: ; WINDOWS: // %bb.0: // %entry ; WINDOWS-NEXT: b ldexp @@ -55,6 +64,10 @@ define float @testExpf(float %val, i32 %a) { ; SVELINUX-NEXT: // kill: def $s0 killed $s0 killed $z0 ; SVELINUX-NEXT: ret ; +; GISEL-LABEL: testExpf: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: b ldexpf +; ; SVEWINDOWS-LABEL: testExpf: ; SVEWINDOWS: // %bb.0: // %entry ; SVEWINDOWS-NEXT: b ldexpf @@ -77,6 +90,10 @@ define float @testExpfIntrinsic(float %val, i32 %a) { ; SVE-NEXT: // kill: def $s0 killed $s0 killed $z0 ; SVE-NEXT: ret ; +; GISEL-LABEL: testExpfIntrinsic: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: b ldexpf +; ; WINDOWS-LABEL: testExpfIntrinsic: ; WINDOWS: .seh_proc testExpfIntrinsic ; WINDOWS-NEXT: // %bb.0: // %entry @@ -98,6 +115,90 @@ entry: ret float %call } +define <2 x float> @test_ldexp_v2f32_v2i32(<2 x float> %Val, <2 x i32> %Exp) { +; SVE-LABEL: test_ldexp_v2f32_v2i32: +; SVE: // %bb.0: +; SVE-NEXT: // kill: def $d1 killed $d1 def $z1 +; SVE-NEXT: mov w8, v1.s[1] +; SVE-NEXT: // kill: def $d0 killed $d0 def $z0 +; SVE-NEXT: mov s2, v0.s[1] +; SVE-NEXT: ptrue p0.s +; SVE-NEXT: fscale z0.s, p0/m, z0.s, z1.s +; SVE-NEXT: fmov s3, w8 +; SVE-NEXT: fscale z2.s, p0/m, z2.s, z3.s +; SVE-NEXT: mov v0.s[1], v2.s[0] +; SVE-NEXT: // kill: def $d0 killed $d0 killed $z0 +; SVE-NEXT: ret +; +; GISEL-LABEL: test_ldexp_v2f32_v2i32: +; GISEL: // %bb.0: +; GISEL-NEXT: sub sp, sp, #48 +; GISEL-NEXT: stp d9, d8, [sp, #16] // 16-byte Folded Spill +; GISEL-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 48 +; GISEL-NEXT: .cfi_offset w30, -16 +; GISEL-NEXT: .cfi_offset b8, -24 +; GISEL-NEXT: .cfi_offset b9, -32 +; GISEL-NEXT: // kill: def $d1 killed $d1 def $q1 +; GISEL-NEXT: fmov w0, s1 +; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 +; GISEL-NEXT: mov s8, v0.s[1] +; GISEL-NEXT: mov s9, v1.s[1] +; GISEL-NEXT: // kill: def $s0 killed $s0 killed $q0 +; GISEL-NEXT: bl ldexpf +; GISEL-NEXT: // kill: def $s0 killed $s0 def $q0 +; GISEL-NEXT: str q0, [sp] // 16-byte Folded Spill +; GISEL-NEXT: fmov w0, s9 +; GISEL-NEXT: fmov s0, s8 +; GISEL-NEXT: bl ldexpf +; GISEL-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; GISEL-NEXT: // kill: def $s0 killed $s0 def $q0 +; GISEL-NEXT: ldp d9, d8, [sp, #16] // 16-byte Folded Reload +; GISEL-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; GISEL-NEXT: mov v1.s[1], v0.s[0] +; GISEL-NEXT: fmov d0, d1 +; GISEL-NEXT: add sp, sp, #48 +; GISEL-NEXT: ret +; +; WINDOWS-LABEL: test_ldexp_v2f32_v2i32: +; WINDOWS: .seh_proc test_ldexp_v2f32_v2i32 +; WINDOWS-NEXT: // %bb.0: +; WINDOWS-NEXT: sub sp, sp, #48 +; WINDOWS-NEXT: .seh_stackalloc 48 +; WINDOWS-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; WINDOWS-NEXT: .seh_save_reg x30, 32 +; WINDOWS-NEXT: .seh_endprologue +; WINDOWS-NEXT: // kill: def $d0 killed $d0 def $q0 +; WINDOWS-NEXT: mov s2, v0.s[1] +; WINDOWS-NEXT: // kill: def $d1 killed $d1 def $q1 +; WINDOWS-NEXT: stp q1, q0, [sp] // 32-byte Folded Spill +; WINDOWS-NEXT: mov w0, v1.s[1] +; WINDOWS-NEXT: fcvt d0, s2 +; WINDOWS-NEXT: bl ldexp +; WINDOWS-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; WINDOWS-NEXT: fcvt s0, d0 +; WINDOWS-NEXT: fcvt d1, s1 +; WINDOWS-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; WINDOWS-NEXT: ldr q0, [sp] // 16-byte Folded Reload +; WINDOWS-NEXT: fmov w0, s0 +; WINDOWS-NEXT: fmov d0, d1 +; WINDOWS-NEXT: bl ldexp +; WINDOWS-NEXT: fcvt s0, d0 +; WINDOWS-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; WINDOWS-NEXT: mov v0.s[1], v1.s[0] +; WINDOWS-NEXT: // kill: def $d0 killed $d0 killed $q0 +; WINDOWS-NEXT: .seh_startepilogue +; WINDOWS-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; WINDOWS-NEXT: .seh_save_reg x30, 32 +; WINDOWS-NEXT: add sp, sp, #48 +; WINDOWS-NEXT: .seh_stackalloc 48 +; WINDOWS-NEXT: .seh_endepilogue +; WINDOWS-NEXT: ret +; WINDOWS-NEXT: .seh_endfunclet +; WINDOWS-NEXT: .seh_endproc + %result = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %Val, <2 x i32> %Exp) + ret <2 x float> %result +} declare float @ldexpf(float, i32) memory(none) @@ -106,6 +207,10 @@ define fp128 @testExpl(fp128 %val, i32 %a) { ; SVE: // %bb.0: // %entry ; SVE-NEXT: b ldexpl ; +; GISEL-LABEL: testExpl: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: b ldexpl +; ; WINDOWS-LABEL: testExpl: ; WINDOWS: // %bb.0: // %entry ; WINDOWS-NEXT: b ldexpl @@ -126,6 +231,17 @@ define half @testExpf16(half %val, i32 %a) { ; SVE-NEXT: fcvt h0, s0 ; SVE-NEXT: ret ; +; GISEL-LABEL: testExpf16: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 16 +; GISEL-NEXT: .cfi_offset w30, -16 +; GISEL-NEXT: fcvt s0, h0 +; GISEL-NEXT: bl ldexpf +; GISEL-NEXT: fcvt h0, s0 +; GISEL-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; GISEL-NEXT: ret +; ; WINDOWS-LABEL: testExpf16: ; WINDOWS: .seh_proc testExpf16 ; WINDOWS-NEXT: // %bb.0: // %entry