Skip to content

Commit 1f88dfe

Browse files
committed
[Windows] Allow legalizing LDEXP_F128 and FREXP_F128 with libcalls
Attempting to use `llvm.ldexp.f128` or `llvm.frexp.f128` on Windows platforms results in a legalization failure. The needed functions `ldexpf128` and `frexpf128` aren't available on Windows, but it should be a failure to link that can be solved by adding a `f128` library is preferable to crashing. Note that due to [44744] this lowering actually incorrectly produces `ldexpl` and `frexpl` symbols, which aren't correct for `_Float128` on Windows. This will be fixed separately. This patch also adds `{frexp,ldexp}.f128` tests on a couple architectures that were missing them, unrelated to the Windows-only change here. Fixes: #144006 [44744]: #44744
1 parent 9de657a commit 1f88dfe

File tree

8 files changed

+345
-2
lines changed

8 files changed

+345
-2
lines changed

llvm/lib/IR/RuntimeLibcalls.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,10 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
206206
if (TT.isOSWindows() && !TT.isOSCygMing()) {
207207
setLibcallImpl(RTLIB::LDEXP_F32, RTLIB::Unsupported);
208208
setLibcallImpl(RTLIB::LDEXP_F80, RTLIB::Unsupported);
209-
setLibcallImpl(RTLIB::LDEXP_F128, RTLIB::Unsupported);
210209
setLibcallImpl(RTLIB::LDEXP_PPCF128, RTLIB::Unsupported);
211210

212211
setLibcallImpl(RTLIB::FREXP_F32, RTLIB::Unsupported);
213212
setLibcallImpl(RTLIB::FREXP_F80, RTLIB::Unsupported);
214-
setLibcallImpl(RTLIB::FREXP_F128, RTLIB::Unsupported);
215213
setLibcallImpl(RTLIB::FREXP_PPCF128, RTLIB::Unsupported);
216214
}
217215

llvm/test/CodeGen/AArch64/ldexp.ll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,17 @@ entry:
147147
ret half %0
148148
}
149149

150+
define fp128 @testExpf128(fp128 %val, i32 %a) {
151+
; SVE-LABEL: testExpf128:
152+
; SVE: // %bb.0: // %entry
153+
; SVE-NEXT: b ldexpl
154+
;
155+
; WINDOWS-LABEL: testExpf128:
156+
; WINDOWS: // %bb.0: // %entry
157+
; WINDOWS-NEXT: b ldexpl
158+
entry:
159+
%ldexp = call fp128 @llvm.ldexp.f128.i32(fp128 %val, i32 %a)
160+
ret fp128 %ldexp
161+
}
162+
150163
declare half @llvm.ldexp.f16.i32(half, i32) memory(none)

llvm/test/CodeGen/AArch64/llvm.frexp.ll

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,6 +1431,73 @@ define <2 x i32> @test_frexp_v2f64_v2i32_only_use_exp(<2 x double> %a) {
14311431
ret <2 x i32> %result.1
14321432
}
14331433

1434+
1435+
define { fp128, i32 } @test_frexp_f128_i32(fp128 %a) nounwind {
1436+
; CHECK-LABEL: test_frexp_f128_i32:
1437+
; CHECK: // %bb.0:
1438+
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1439+
; CHECK-NEXT: add x0, sp, #12
1440+
; CHECK-NEXT: bl frexpl
1441+
; CHECK-NEXT: ldr w0, [sp, #12]
1442+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1443+
; CHECK-NEXT: ret
1444+
;
1445+
; WINDOWS-LABEL: test_frexp_f128_i32:
1446+
; WINDOWS: // %bb.0:
1447+
; WINDOWS-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1448+
; WINDOWS-NEXT: add x0, sp, #12
1449+
; WINDOWS-NEXT: bl frexpl
1450+
; WINDOWS-NEXT: ldr w0, [sp, #12]
1451+
; WINDOWS-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1452+
; WINDOWS-NEXT: ret
1453+
%result = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %a)
1454+
ret { fp128, i32 } %result
1455+
}
1456+
1457+
define fp128 @test_frexp_f128_i32_only_use_fract(fp128 %a) nounwind {
1458+
; CHECK-LABEL: test_frexp_f128_i32_only_use_fract:
1459+
; CHECK: // %bb.0:
1460+
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1461+
; CHECK-NEXT: add x0, sp, #12
1462+
; CHECK-NEXT: bl frexpl
1463+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1464+
; CHECK-NEXT: ret
1465+
;
1466+
; WINDOWS-LABEL: test_frexp_f128_i32_only_use_fract:
1467+
; WINDOWS: // %bb.0:
1468+
; WINDOWS-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1469+
; WINDOWS-NEXT: add x0, sp, #12
1470+
; WINDOWS-NEXT: bl frexpl
1471+
; WINDOWS-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1472+
; WINDOWS-NEXT: ret
1473+
%result = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %a)
1474+
%result.0 = extractvalue { fp128, i32 } %result, 0
1475+
ret fp128 %result.0
1476+
}
1477+
1478+
define i32 @test_frexp_f128_i32_only_use_exp(fp128 %a) nounwind {
1479+
; CHECK-LABEL: test_frexp_f128_i32_only_use_exp:
1480+
; CHECK: // %bb.0:
1481+
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1482+
; CHECK-NEXT: add x0, sp, #12
1483+
; CHECK-NEXT: bl frexpl
1484+
; CHECK-NEXT: ldr w0, [sp, #12]
1485+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1486+
; CHECK-NEXT: ret
1487+
;
1488+
; WINDOWS-LABEL: test_frexp_f128_i32_only_use_exp:
1489+
; WINDOWS: // %bb.0:
1490+
; WINDOWS-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1491+
; WINDOWS-NEXT: add x0, sp, #12
1492+
; WINDOWS-NEXT: bl frexpl
1493+
; WINDOWS-NEXT: ldr w0, [sp, #12]
1494+
; WINDOWS-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1495+
; WINDOWS-NEXT: ret
1496+
%result = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %a)
1497+
%result.0 = extractvalue { fp128, i32 } %result, 1
1498+
ret i32 %result.0
1499+
}
1500+
14341501
declare { float, i32 } @llvm.frexp.f32.i32(float) #0
14351502
declare { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float>) #0
14361503
declare { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float>) #0

llvm/test/CodeGen/ARM/ldexp.ll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,12 @@ entry:
5555
ret half %0
5656
}
5757

58+
define fp128 @testExpf128(fp128 %val, i32 %a) {
59+
; LINUX: bl ldexpl
60+
; WINDOWS: bl ldexpl
61+
entry:
62+
%0 = tail call fp128 @llvm.ldexp.f128.i32(fp128 %val, i32 %a)
63+
ret fp128 %0
64+
}
65+
5866
declare half @llvm.ldexp.f16.i32(half, i32) memory(none)

llvm/test/CodeGen/ARM/llvm.frexp.ll

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,59 @@ define <2 x i32> @test_frexp_v2f64_v2i32_only_use_exp(<2 x double> %a) {
544544
ret <2 x i32> %result.1
545545
}
546546

547+
define { fp128, i32 } @test_frexp_f128_i32(fp128 %a) nounwind {
548+
; CHECK-LABEL: test_frexp_f128_i32:
549+
; CHECK: @ %bb.0:
550+
; CHECK-NEXT: push {r4, lr}
551+
; CHECK-NEXT: sub sp, #8
552+
; CHECK-NEXT: mov r12, r3
553+
; CHECK-NEXT: ldr r3, [sp, #16]
554+
; CHECK-NEXT: mov r4, r0
555+
; CHECK-NEXT: add r0, sp, #4
556+
; CHECK-NEXT: str r0, [sp]
557+
; CHECK-NEXT: mov r0, r1
558+
; CHECK-NEXT: mov r1, r2
559+
; CHECK-NEXT: mov r2, r12
560+
; CHECK-NEXT: bl frexpl
561+
; CHECK-NEXT: ldr.w r12, [sp, #4]
562+
; CHECK-NEXT: stm.w r4, {r0, r1, r2, r3, r12}
563+
; CHECK-NEXT: add sp, #8
564+
; CHECK-NEXT: pop {r4, pc}
565+
%result = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %a)
566+
ret { fp128, i32 } %result
567+
}
568+
569+
define fp128 @test_frexp_f128_i32_only_use_fract(fp128 %a) nounwind {
570+
; CHECK-LABEL: test_frexp_f128_i32_only_use_fract:
571+
; CHECK: @ %bb.0:
572+
; CHECK-NEXT: push {r7, lr}
573+
; CHECK-NEXT: sub sp, #8
574+
; CHECK-NEXT: add.w r12, sp, #4
575+
; CHECK-NEXT: str.w r12, [sp]
576+
; CHECK-NEXT: bl frexpl
577+
; CHECK-NEXT: add sp, #8
578+
; CHECK-NEXT: pop {r7, pc}
579+
%result = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %a)
580+
%result.0 = extractvalue { fp128, i32 } %result, 0
581+
ret fp128 %result.0
582+
}
583+
584+
define i32 @test_frexp_f128_i32_only_use_exp(fp128 %a) nounwind {
585+
; CHECK-LABEL: test_frexp_f128_i32_only_use_exp:
586+
; CHECK: @ %bb.0:
587+
; CHECK-NEXT: push {r7, lr}
588+
; CHECK-NEXT: sub sp, #8
589+
; CHECK-NEXT: add.w r12, sp, #4
590+
; CHECK-NEXT: str.w r12, [sp]
591+
; CHECK-NEXT: bl frexpl
592+
; CHECK-NEXT: ldr r0, [sp, #4]
593+
; CHECK-NEXT: add sp, #8
594+
; CHECK-NEXT: pop {r7, pc}
595+
%result = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %a)
596+
%result.0 = extractvalue { fp128, i32 } %result, 1
597+
ret i32 %result.0
598+
}
599+
547600
declare { float, i32 } @llvm.frexp.f32.i32(float) #0
548601
declare { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float>) #0
549602
declare { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float>) #0

llvm/test/CodeGen/Mips/ldexp.ll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,20 @@ define x86_fp80 @ldexp_f80(x86_fp80 %arg0, i32 %arg1) {
161161
ret x86_fp80 %ldexp
162162
}
163163

164+
define fp128 @ldexp_f128(fp128 %arg0, i32 %arg1) nounwind {
165+
; SOFT-LABEL: ldexp_f128:
166+
; SOFT: # %bb.0:
167+
; SOFT-NEXT: addiu $sp, $sp, -32
168+
; SOFT-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill
169+
; SOFT-NEXT: lw $1, 48($sp)
170+
; SOFT-NEXT: jal ldexpl
171+
; SOFT-NEXT: sw $1, 16($sp)
172+
; SOFT-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload
173+
; SOFT-NEXT: jr $ra
174+
; SOFT-NEXT: addiu $sp, $sp, 32
175+
%ldexp = call fp128 @llvm.ldexp.f128.i32(fp128 %arg0, i32 %arg1)
176+
ret fp128 %ldexp
177+
}
164178

165179
declare double @llvm.ldexp.f64.i32(double, i32) #0
166180
declare float @llvm.ldexp.f32.i32(float, i32) #0

llvm/test/CodeGen/X86/ldexp.ll

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,63 @@ define half @ldexp_f16(half %arg0, i32 %arg1) {
623623
ret half %ldexp
624624
}
625625

626+
define fp128 @ldexp_f128(fp128 %arg0, i32 %arg1) {
627+
; X64-LABEL: ldexp_f128:
628+
; X64: # %bb.0:
629+
; X64-NEXT: jmp ldexpl@PLT # TAILCALL
630+
;
631+
; WIN64-LABEL: ldexp_f128:
632+
; WIN64: # %bb.0:
633+
; WIN64-NEXT: subq $56, %rsp
634+
; WIN64-NEXT: .seh_stackalloc 56
635+
; WIN64-NEXT: .seh_endprologue
636+
; WIN64-NEXT: movaps (%rcx), %xmm0
637+
; WIN64-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
638+
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
639+
; WIN64-NEXT: callq ldexpl
640+
; WIN64-NEXT: nop
641+
; WIN64-NEXT: .seh_startepilogue
642+
; WIN64-NEXT: addq $56, %rsp
643+
; WIN64-NEXT: .seh_endepilogue
644+
; WIN64-NEXT: retq
645+
; WIN64-NEXT: .seh_endproc
646+
;
647+
; WIN32-LABEL: ldexp_f128:
648+
; WIN32: # %bb.0:
649+
; WIN32-NEXT: pushl %ebp
650+
; WIN32-NEXT: movl %esp, %ebp
651+
; WIN32-NEXT: pushl %edi
652+
; WIN32-NEXT: pushl %esi
653+
; WIN32-NEXT: andl $-16, %esp
654+
; WIN32-NEXT: subl $16, %esp
655+
; WIN32-NEXT: movl 8(%ebp), %esi
656+
; WIN32-NEXT: movl %esp, %eax
657+
; WIN32-NEXT: pushl 28(%ebp)
658+
; WIN32-NEXT: pushl 24(%ebp)
659+
; WIN32-NEXT: pushl 20(%ebp)
660+
; WIN32-NEXT: pushl 16(%ebp)
661+
; WIN32-NEXT: pushl 12(%ebp)
662+
; WIN32-NEXT: pushl %eax
663+
; WIN32-NEXT: calll _ldexpl
664+
; WIN32-NEXT: addl $24, %esp
665+
; WIN32-NEXT: movl (%esp), %eax
666+
; WIN32-NEXT: movl {{[0-9]+}}(%esp), %ecx
667+
; WIN32-NEXT: movl {{[0-9]+}}(%esp), %edx
668+
; WIN32-NEXT: movl {{[0-9]+}}(%esp), %edi
669+
; WIN32-NEXT: movl %edi, 12(%esi)
670+
; WIN32-NEXT: movl %edx, 8(%esi)
671+
; WIN32-NEXT: movl %ecx, 4(%esi)
672+
; WIN32-NEXT: movl %eax, (%esi)
673+
; WIN32-NEXT: movl %esi, %eax
674+
; WIN32-NEXT: leal -8(%ebp), %esp
675+
; WIN32-NEXT: popl %esi
676+
; WIN32-NEXT: popl %edi
677+
; WIN32-NEXT: popl %ebp
678+
; WIN32-NEXT: retl
679+
%ldexp = call fp128 @llvm.ldexp.f128.i32(fp128 %arg0, i32 %arg1)
680+
ret fp128 %ldexp
681+
}
682+
626683
declare double @llvm.ldexp.f64.i32(double, i32) #0
627684
declare float @llvm.ldexp.f32.i32(float, i32) #0
628685
declare <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float>, <2 x i32>) #0

0 commit comments

Comments
 (0)