Skip to content

Commit fd1fb1b

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. [44744]: #44744 Fixes: #144006
1 parent 0db197a commit fd1fb1b

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
@@ -1131,6 +1131,73 @@ define <2 x i32> @test_frexp_v2f64_v2i32_only_use_exp(<2 x double> %a) nounwind
11311131
ret <2 x i32> %result.1
11321132
}
11331133

1134+
1135+
define { fp128, i32 } @test_frexp_f128_i32(fp128 %a) nounwind {
1136+
; CHECK-LABEL: test_frexp_f128_i32:
1137+
; CHECK: // %bb.0:
1138+
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1139+
; CHECK-NEXT: add x0, sp, #12
1140+
; CHECK-NEXT: bl frexpl
1141+
; CHECK-NEXT: ldr w0, [sp, #12]
1142+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1143+
; CHECK-NEXT: ret
1144+
;
1145+
; WINDOWS-LABEL: test_frexp_f128_i32:
1146+
; WINDOWS: // %bb.0:
1147+
; WINDOWS-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1148+
; WINDOWS-NEXT: add x0, sp, #12
1149+
; WINDOWS-NEXT: bl frexpl
1150+
; WINDOWS-NEXT: ldr w0, [sp, #12]
1151+
; WINDOWS-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1152+
; WINDOWS-NEXT: ret
1153+
%result = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %a)
1154+
ret { fp128, i32 } %result
1155+
}
1156+
1157+
define fp128 @test_frexp_f128_i32_only_use_fract(fp128 %a) nounwind {
1158+
; CHECK-LABEL: test_frexp_f128_i32_only_use_fract:
1159+
; CHECK: // %bb.0:
1160+
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1161+
; CHECK-NEXT: add x0, sp, #12
1162+
; CHECK-NEXT: bl frexpl
1163+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1164+
; CHECK-NEXT: ret
1165+
;
1166+
; WINDOWS-LABEL: test_frexp_f128_i32_only_use_fract:
1167+
; WINDOWS: // %bb.0:
1168+
; WINDOWS-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1169+
; WINDOWS-NEXT: add x0, sp, #12
1170+
; WINDOWS-NEXT: bl frexpl
1171+
; WINDOWS-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1172+
; WINDOWS-NEXT: ret
1173+
%result = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %a)
1174+
%result.0 = extractvalue { fp128, i32 } %result, 0
1175+
ret fp128 %result.0
1176+
}
1177+
1178+
define i32 @test_frexp_f128_i32_only_use_exp(fp128 %a) nounwind {
1179+
; CHECK-LABEL: test_frexp_f128_i32_only_use_exp:
1180+
; CHECK: // %bb.0:
1181+
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1182+
; CHECK-NEXT: add x0, sp, #12
1183+
; CHECK-NEXT: bl frexpl
1184+
; CHECK-NEXT: ldr w0, [sp, #12]
1185+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1186+
; CHECK-NEXT: ret
1187+
;
1188+
; WINDOWS-LABEL: test_frexp_f128_i32_only_use_exp:
1189+
; WINDOWS: // %bb.0:
1190+
; WINDOWS-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1191+
; WINDOWS-NEXT: add x0, sp, #12
1192+
; WINDOWS-NEXT: bl frexpl
1193+
; WINDOWS-NEXT: ldr w0, [sp, #12]
1194+
; WINDOWS-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1195+
; WINDOWS-NEXT: ret
1196+
%result = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %a)
1197+
%result.0 = extractvalue { fp128, i32 } %result, 1
1198+
ret i32 %result.0
1199+
}
1200+
11341201
declare { float, i32 } @llvm.frexp.f32.i32(float) #0
11351202
declare { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float>) #0
11361203
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
@@ -141,6 +141,20 @@ define x86_fp80 @ldexp_f80(x86_fp80 %arg0, i32 %arg1) nounwind {
141141
ret x86_fp80 %ldexp
142142
}
143143

144+
define fp128 @ldexp_f128(fp128 %arg0, i32 %arg1) nounwind {
145+
; SOFT-LABEL: ldexp_f128:
146+
; SOFT: # %bb.0:
147+
; SOFT-NEXT: addiu $sp, $sp, -32
148+
; SOFT-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill
149+
; SOFT-NEXT: lw $1, 48($sp)
150+
; SOFT-NEXT: jal ldexpl
151+
; SOFT-NEXT: sw $1, 16($sp)
152+
; SOFT-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload
153+
; SOFT-NEXT: jr $ra
154+
; SOFT-NEXT: addiu $sp, $sp, 32
155+
%ldexp = call fp128 @llvm.ldexp.f128.i32(fp128 %arg0, i32 %arg1)
156+
ret fp128 %ldexp
157+
}
144158

145159
declare double @llvm.ldexp.f64.i32(double, i32) #0
146160
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
@@ -557,6 +557,63 @@ define half @ldexp_f16(half %arg0, i32 %arg1) nounwind {
557557
ret half %ldexp
558558
}
559559

560+
define fp128 @ldexp_f128(fp128 %arg0, i32 %arg1) nounwind {
561+
; X64-LABEL: ldexp_f128:
562+
; X64: # %bb.0:
563+
; X64-NEXT: jmp ldexpl@PLT # TAILCALL
564+
;
565+
; WIN64-LABEL: ldexp_f128:
566+
; WIN64: # %bb.0:
567+
; WIN64-NEXT: subq $56, %rsp
568+
; WIN64-NEXT: .seh_stackalloc 56
569+
; WIN64-NEXT: .seh_endprologue
570+
; WIN64-NEXT: movaps (%rcx), %xmm0
571+
; WIN64-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
572+
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
573+
; WIN64-NEXT: callq ldexpl
574+
; WIN64-NEXT: nop
575+
; WIN64-NEXT: .seh_startepilogue
576+
; WIN64-NEXT: addq $56, %rsp
577+
; WIN64-NEXT: .seh_endepilogue
578+
; WIN64-NEXT: retq
579+
; WIN64-NEXT: .seh_endproc
580+
;
581+
; WIN32-LABEL: ldexp_f128:
582+
; WIN32: # %bb.0:
583+
; WIN32-NEXT: pushl %ebp
584+
; WIN32-NEXT: movl %esp, %ebp
585+
; WIN32-NEXT: pushl %edi
586+
; WIN32-NEXT: pushl %esi
587+
; WIN32-NEXT: andl $-16, %esp
588+
; WIN32-NEXT: subl $16, %esp
589+
; WIN32-NEXT: movl 8(%ebp), %esi
590+
; WIN32-NEXT: movl %esp, %eax
591+
; WIN32-NEXT: pushl 28(%ebp)
592+
; WIN32-NEXT: pushl 24(%ebp)
593+
; WIN32-NEXT: pushl 20(%ebp)
594+
; WIN32-NEXT: pushl 16(%ebp)
595+
; WIN32-NEXT: pushl 12(%ebp)
596+
; WIN32-NEXT: pushl %eax
597+
; WIN32-NEXT: calll _ldexpl
598+
; WIN32-NEXT: addl $24, %esp
599+
; WIN32-NEXT: movl (%esp), %eax
600+
; WIN32-NEXT: movl {{[0-9]+}}(%esp), %ecx
601+
; WIN32-NEXT: movl {{[0-9]+}}(%esp), %edx
602+
; WIN32-NEXT: movl {{[0-9]+}}(%esp), %edi
603+
; WIN32-NEXT: movl %edi, 12(%esi)
604+
; WIN32-NEXT: movl %edx, 8(%esi)
605+
; WIN32-NEXT: movl %ecx, 4(%esi)
606+
; WIN32-NEXT: movl %eax, (%esi)
607+
; WIN32-NEXT: movl %esi, %eax
608+
; WIN32-NEXT: leal -8(%ebp), %esp
609+
; WIN32-NEXT: popl %esi
610+
; WIN32-NEXT: popl %edi
611+
; WIN32-NEXT: popl %ebp
612+
; WIN32-NEXT: retl
613+
%ldexp = call fp128 @llvm.ldexp.f128.i32(fp128 %arg0, i32 %arg1)
614+
ret fp128 %ldexp
615+
}
616+
560617
declare double @llvm.ldexp.f64.i32(double, i32) #0
561618
declare float @llvm.ldexp.f32.i32(float, i32) #0
562619
declare <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float>, <2 x i32>) #0

0 commit comments

Comments
 (0)