[llvm-branch-commits] [llvm] RuntimeLibcalls: Stop providing __powitf2 on MSVCRT (PR #216987)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Aug 18 04:06:26 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Matt Arsenault (arsenm)

<details>
<summary>Changes</summary>

MSVCRT does not provide the powi helpers, so gate the fp128 __powitf2 on
isNotOSMSVCRT alongside the f32/f64 __powisf2/__powidf2, instead of adding it
unconditionally. The unconditional add was a hack to satisfy a test that
expected a wrongly-typed powi call on windows-msvc.

Co-authored-by: Claude (Opus 4.8) <noreply@<!-- -->anthropic.com>

---
Full diff: https://github.com/llvm/llvm-project/pull/216987.diff


3 Files Affected:

- (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+2-4) 
- (modified) llvm/test/CodeGen/X86/fp128-libcalls-strict.ll (+22-133) 
- (added) llvm/test/CodeGen/X86/fp128-powi-strict.ll (+67) 


``````````diff
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 8cbb3231571ac..078a3a39146ad 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -3466,11 +3466,9 @@ defvar X86CommonLibcalls =
        LibcallImpls<(add X86LongDoubleF128Body), isLongDoubleF128>,
        LibmHasExp10F32, LibmHasExp10F64,
        LibcallImpls<(add exp10l_f80), isLongDoubleX87AndHasExp10>,
-       LibcallImpls<(add __powisf2, __powidf2), isNotOSMSVCRT>,
+       // MSVCRT does not provide the powi helpers.
+       LibcallImpls<(add __powisf2, __powidf2, __powitf2_f128), isNotOSMSVCRT>,
        SecurityCheckCookieIfWinMSVC,
-       // FIXME: MSVCRT doesn't have powi. The f128 case is added as a
-       // hack for one test relying on it.
-       __powitf2_f128,
        DefaultStackProtector,
        DefaultSafeStackGlobals,
        LibcallImpls<(add MemChkLibcalls), isNotPS>,
diff --git a/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll b/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll
index 390baa03abdec..df0bb575241d9 100644
--- a/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll
+++ b/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll
@@ -15,10 +15,12 @@
 ; RUN:     -enable-legalize-types-checking \
 ; RUN:     | FileCheck %s --check-prefix=WIN-X86
 
-; NOTE: Only fp128 arithmetic (add/sub/mul/div), powi and the compares have a
-; libcall on every triple here. The strict fp128 math/rem/fma/rounding/lrint
-; cases only have a libcall where libc provides the f128-suffixed functions
-; (glibc); those are covered in fp128-libcalls-strict-gnu.ll.
+; NOTE: Only fp128 arithmetic (add/sub/mul/div) and the compares have a libcall
+; on every triple here. The strict fp128 math/rem/fma/rounding/lrint cases only
+; have a libcall where libc provides the f128-suffixed functions (glibc); those
+; are covered in fp128-libcalls-strict-gnu.ll. powi is covered in
+; fp128-powi-strict.ll (and the MSVCRT no-libcall case in
+; fp128-powi-strict-no-libcall-error.ll).
 
 ; Check all soft floating point library function calls.
 
@@ -538,118 +540,6 @@ entry:
   ret fp128 %div
 }
 
-define fp128 @powi(fp128 %x, i32 %y) nounwind strictfp {
-; CHECK-LABEL: powi:
-; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    pushq %rax
-; CHECK-NEXT:    callq __powitf2 at PLT
-; CHECK-NEXT:    popq %rax
-; CHECK-NEXT:    retq
-;
-; ANDROID-LABEL: powi:
-; ANDROID:       # %bb.0: # %entry
-; ANDROID-NEXT:    pushq %rax
-; ANDROID-NEXT:    callq __powitf2 at PLT
-; ANDROID-NEXT:    popq %rax
-; ANDROID-NEXT:    retq
-;
-; GNU-LABEL: powi:
-; GNU:       # %bb.0: # %entry
-; GNU-NEXT:    pushq %rax
-; GNU-NEXT:    callq __powitf2 at PLT
-; GNU-NEXT:    popq %rax
-; GNU-NEXT:    retq
-;
-; X86-LABEL: powi:
-; X86:       # %bb.0: # %entry
-; X86-NEXT:    pushl %ebx
-; X86-NEXT:    pushl %edi
-; X86-NEXT:    pushl %esi
-; X86-NEXT:    subl $64, %esp
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebx
-; X86-NEXT:    movl %ebx, {{[0-9]+}}(%esp)
-; X86-NEXT:    movl %edi, {{[0-9]+}}(%esp)
-; X86-NEXT:    movl %edx, {{[0-9]+}}(%esp)
-; X86-NEXT:    movl %ecx, {{[0-9]+}}(%esp)
-; X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
-; X86-NEXT:    leal {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    movl %eax, (%esp)
-; X86-NEXT:    calll __powitf2
-; X86-NEXT:    subl $4, %esp
-; X86-NEXT:    movaps {{[0-9]+}}(%esp), %xmm0
-; X86-NEXT:    movaps %xmm0, (%esi)
-; X86-NEXT:    movl %esi, %eax
-; X86-NEXT:    addl $64, %esp
-; X86-NEXT:    popl %esi
-; X86-NEXT:    popl %edi
-; X86-NEXT:    popl %ebx
-; X86-NEXT:    retl $4
-;
-; WIN-LABEL: powi:
-; WIN:       # %bb.0: # %entry
-; WIN-NEXT:    pushq %rsi
-; WIN-NEXT:    subq $64, %rsp
-; WIN-NEXT:    movq %rcx, %rsi
-; WIN-NEXT:    movaps (%rdx), %xmm0
-; WIN-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
-; WIN-NEXT:    leaq {{[0-9]+}}(%rsp), %rcx
-; WIN-NEXT:    leaq {{[0-9]+}}(%rsp), %rdx
-; WIN-NEXT:    callq __powitf2
-; WIN-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm0
-; WIN-NEXT:    movaps %xmm0, (%rsi)
-; WIN-NEXT:    movq %rsi, %rax
-; WIN-NEXT:    addq $64, %rsp
-; WIN-NEXT:    popq %rsi
-; WIN-NEXT:    retq
-;
-; WIN-X86-LABEL: powi:
-; WIN-X86:       # %bb.0: # %entry
-; WIN-X86-NEXT:    pushl %ebp
-; WIN-X86-NEXT:    movl %esp, %ebp
-; WIN-X86-NEXT:    pushl %ebx
-; WIN-X86-NEXT:    pushl %edi
-; WIN-X86-NEXT:    pushl %esi
-; WIN-X86-NEXT:    andl $-16, %esp
-; WIN-X86-NEXT:    subl $80, %esp
-; WIN-X86-NEXT:    movl 8(%ebp), %esi
-; WIN-X86-NEXT:    movl 24(%ebp), %eax
-; WIN-X86-NEXT:    movl 28(%ebp), %ecx
-; WIN-X86-NEXT:    movl 32(%ebp), %edx
-; WIN-X86-NEXT:    movl 36(%ebp), %edi
-; WIN-X86-NEXT:    movl 40(%ebp), %ebx
-; WIN-X86-NEXT:    movl %ebx, {{[0-9]+}}(%esp)
-; WIN-X86-NEXT:    movl %edi, {{[0-9]+}}(%esp)
-; WIN-X86-NEXT:    movl %edx, {{[0-9]+}}(%esp)
-; WIN-X86-NEXT:    movl %ecx, {{[0-9]+}}(%esp)
-; WIN-X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
-; WIN-X86-NEXT:    leal {{[0-9]+}}(%esp), %eax
-; WIN-X86-NEXT:    movl %eax, (%esp)
-; WIN-X86-NEXT:    calll ___powitf2
-; WIN-X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; WIN-X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; WIN-X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; WIN-X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
-; WIN-X86-NEXT:    movl %edi, 8(%esi)
-; WIN-X86-NEXT:    movl %edx, 12(%esi)
-; WIN-X86-NEXT:    movl %eax, (%esi)
-; WIN-X86-NEXT:    movl %ecx, 4(%esi)
-; WIN-X86-NEXT:    movl %esi, %eax
-; WIN-X86-NEXT:    leal -12(%ebp), %esp
-; WIN-X86-NEXT:    popl %esi
-; WIN-X86-NEXT:    popl %edi
-; WIN-X86-NEXT:    popl %ebx
-; WIN-X86-NEXT:    popl %ebp
-; WIN-X86-NEXT:    retl
-entry:
-  %powi = call fp128 @llvm.experimental.constrained.powi.f128(fp128 %x, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
-  ret fp128 %powi
-}
-
 define i64 @cmp(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 {
 ; CHECK-LABEL: cmp:
 ; CHECK:       # %bb.0:
@@ -760,13 +650,13 @@ define i64 @cmp(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 {
 ; WIN-X86-NEXT:    calll ___eqtf2
 ; WIN-X86-NEXT:    addl $32, %esp
 ; WIN-X86-NEXT:    testl %eax, %eax
-; WIN-X86-NEXT:    je LBB5_1
+; WIN-X86-NEXT:    je LBB4_1
 ; WIN-X86-NEXT:  # %bb.2:
 ; WIN-X86-NEXT:    leal 16(%ebp), %ecx
-; WIN-X86-NEXT:    jmp LBB5_3
-; WIN-X86-NEXT:  LBB5_1:
+; WIN-X86-NEXT:    jmp LBB4_3
+; WIN-X86-NEXT:  LBB4_1:
 ; WIN-X86-NEXT:    leal 8(%ebp), %ecx
-; WIN-X86-NEXT:  LBB5_3:
+; WIN-X86-NEXT:  LBB4_3:
 ; WIN-X86-NEXT:    movl (%ecx), %eax
 ; WIN-X86-NEXT:    movl 4(%ecx), %edx
 ; WIN-X86-NEXT:    movl %ebp, %esp
@@ -890,13 +780,13 @@ define i64 @cmps(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 {
 ; WIN-X86-NEXT:    calll ___eqtf2
 ; WIN-X86-NEXT:    addl $32, %esp
 ; WIN-X86-NEXT:    testl %eax, %eax
-; WIN-X86-NEXT:    je LBB6_1
+; WIN-X86-NEXT:    je LBB5_1
 ; WIN-X86-NEXT:  # %bb.2:
 ; WIN-X86-NEXT:    leal 16(%ebp), %ecx
-; WIN-X86-NEXT:    jmp LBB6_3
-; WIN-X86-NEXT:  LBB6_1:
+; WIN-X86-NEXT:    jmp LBB5_3
+; WIN-X86-NEXT:  LBB5_1:
 ; WIN-X86-NEXT:    leal 8(%ebp), %ecx
-; WIN-X86-NEXT:  LBB6_3:
+; WIN-X86-NEXT:  LBB5_3:
 ; WIN-X86-NEXT:    movl (%ecx), %eax
 ; WIN-X86-NEXT:    movl 4(%ecx), %edx
 ; WIN-X86-NEXT:    movl %ebp, %esp
@@ -1110,13 +1000,13 @@ define i64 @cmp_ueq_q(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 {
 ; WIN-X86-NEXT:    addl $32, %esp
 ; WIN-X86-NEXT:    orb %bl, %al
 ; WIN-X86-NEXT:    testb $1, %al
-; WIN-X86-NEXT:    jne LBB7_1
+; WIN-X86-NEXT:    jne LBB6_1
 ; WIN-X86-NEXT:  # %bb.2:
 ; WIN-X86-NEXT:    leal 16(%ebp), %ecx
-; WIN-X86-NEXT:    jmp LBB7_3
-; WIN-X86-NEXT:  LBB7_1:
+; WIN-X86-NEXT:    jmp LBB6_3
+; WIN-X86-NEXT:  LBB6_1:
 ; WIN-X86-NEXT:    leal 8(%ebp), %ecx
-; WIN-X86-NEXT:  LBB7_3:
+; WIN-X86-NEXT:  LBB6_3:
 ; WIN-X86-NEXT:    movl (%ecx), %eax
 ; WIN-X86-NEXT:    movl 4(%ecx), %edx
 ; WIN-X86-NEXT:    leal -12(%ebp), %esp
@@ -1335,13 +1225,13 @@ define i64 @cmp_one_q(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 {
 ; WIN-X86-NEXT:    testl %eax, %eax
 ; WIN-X86-NEXT:    sete %al
 ; WIN-X86-NEXT:    testb %bl, %al
-; WIN-X86-NEXT:    jne LBB8_1
+; WIN-X86-NEXT:    jne LBB7_1
 ; WIN-X86-NEXT:  # %bb.2:
 ; WIN-X86-NEXT:    leal 16(%ebp), %ecx
-; WIN-X86-NEXT:    jmp LBB8_3
-; WIN-X86-NEXT:  LBB8_1:
+; WIN-X86-NEXT:    jmp LBB7_3
+; WIN-X86-NEXT:  LBB7_1:
 ; WIN-X86-NEXT:    leal 8(%ebp), %ecx
-; WIN-X86-NEXT:  LBB8_3:
+; WIN-X86-NEXT:  LBB7_3:
 ; WIN-X86-NEXT:    movl (%ecx), %eax
 ; WIN-X86-NEXT:    movl 4(%ecx), %edx
 ; WIN-X86-NEXT:    leal -12(%ebp), %esp
@@ -1364,6 +1254,5 @@ declare fp128 @llvm.experimental.constrained.fadd.f128(fp128, fp128, metadata, m
 declare fp128 @llvm.experimental.constrained.fsub.f128(fp128, fp128, metadata, metadata)
 declare fp128 @llvm.experimental.constrained.fmul.f128(fp128, fp128, metadata, metadata)
 declare fp128 @llvm.experimental.constrained.fdiv.f128(fp128, fp128, metadata, metadata)
-declare fp128 @llvm.experimental.constrained.powi.f128(fp128, i32, metadata, metadata)
 declare i1 @llvm.experimental.constrained.fcmp.f128(fp128, fp128, metadata, metadata)
 declare i1 @llvm.experimental.constrained.fcmps.f128(fp128, fp128, metadata, metadata)
diff --git a/llvm/test/CodeGen/X86/fp128-powi-strict.ll b/llvm/test/CodeGen/X86/fp128-powi-strict.ll
new file mode 100644
index 0000000000000..197ab3b6e996d
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fp128-powi-strict.ll
@@ -0,0 +1,67 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64-linux-android -enable-legalize-types-checking < %s | FileCheck %s --check-prefix=ANDROID
+; RUN: llc -mtriple=x86_64-linux-gnu -enable-legalize-types-checking < %s | FileCheck %s --check-prefix=GNU
+; RUN: llc -mtriple=i686-linux-gnu -mattr=+sse2 -enable-legalize-types-checking < %s | FileCheck %s --check-prefix=X86
+
+; RUN: not llc < %s -mtriple=x86_64-pc-windows-msvc -filetype=null 2>&1 | FileCheck %s --check-prefix=WIN
+; RUN: not llc < %s -mtriple=i686-pc-windows-msvc -mattr=+sse2 -filetype=null 2>&1 | FileCheck %s --check-prefix=WIN-X86
+
+; The fp128 powi libcall (__powitf2) is provided by compiler-rt /
+; libgcc on the targets below. MSVCRT does not provide it, so
+; windows-msvc must diagnose a missing libcall instead.
+
+; WIN: error: no libcall available for strict_fpow
+; WIN-X86: error: do not know how to soften fpowi to fpow
+
+define fp128 @powi(fp128 %x, i32 %y) nounwind strictfp {
+; ANDROID-LABEL: powi:
+; ANDROID:       # %bb.0: # %entry
+; ANDROID-NEXT:    pushq %rax
+; ANDROID-NEXT:    callq __powitf2 at PLT
+; ANDROID-NEXT:    popq %rax
+; ANDROID-NEXT:    retq
+;
+; GNU-LABEL: powi:
+; GNU:       # %bb.0: # %entry
+; GNU-NEXT:    pushq %rax
+; GNU-NEXT:    callq __powitf2 at PLT
+; GNU-NEXT:    popq %rax
+; GNU-NEXT:    retq
+;
+; X86-LABEL: powi:
+; X86:       # %bb.0: # %entry
+; X86-NEXT:    pushl %ebx
+; X86-NEXT:    pushl %edi
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    subl $64, %esp
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebx
+; X86-NEXT:    movl %ebx, {{[0-9]+}}(%esp)
+; X86-NEXT:    movl %edi, {{[0-9]+}}(%esp)
+; X86-NEXT:    movl %edx, {{[0-9]+}}(%esp)
+; X86-NEXT:    movl %ecx, {{[0-9]+}}(%esp)
+; X86-NEXT:    movl %eax, {{[0-9]+}}(%esp)
+; X86-NEXT:    leal {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl %eax, (%esp)
+; X86-NEXT:    calll __powitf2
+; X86-NEXT:    subl $4, %esp
+; X86-NEXT:    movaps {{[0-9]+}}(%esp), %xmm0
+; X86-NEXT:    movaps %xmm0, (%esi)
+; X86-NEXT:    movl %esi, %eax
+; X86-NEXT:    addl $64, %esp
+; X86-NEXT:    popl %esi
+; X86-NEXT:    popl %edi
+; X86-NEXT:    popl %ebx
+; X86-NEXT:    retl $4
+entry:
+  %powi = call fp128 @llvm.experimental.constrained.powi.f128(fp128 %x, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret fp128 %powi
+}
+
+declare fp128 @llvm.experimental.constrained.powi.f128(fp128, i32, metadata, metadata)
+
+attributes #0 = { strictfp }

``````````

</details>


https://github.com/llvm/llvm-project/pull/216987


More information about the llvm-branch-commits mailing list