[llvm] [InstCombine] Fold scalbn libcalls to llvm.ldexp (PR #216573)

Hadong Lee via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 06:21:08 PDT 2026


================
@@ -0,0 +1,78 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+declare float @scalbnf(float, i32)
+declare double @scalbn(double, i32)
+declare fp128 @scalbnl(fp128, i32)
+
+; Cover the float variant and preservation of fast-math flags and tail calls.
+
+define float @scalbnf_f32(float %x, i32 %exp) {
+; CHECK-LABEL: define float @scalbnf_f32(
+; CHECK-SAME: float [[X:%.*]], i32 [[EXP:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = tail call fast float @llvm.ldexp.f32.i32(float [[X]], i32 [[EXP]])
+; CHECK-NEXT:    ret float [[R]]
+;
+  %r = tail call fast float @scalbnf(float %x, i32 %exp) memory(none)
+  ret float %r
+}
+
+; Cover the double variant.
+
+define double @scalbn_f64(double %x, i32 %exp) {
+; CHECK-LABEL: define double @scalbn_f64(
+; CHECK-SAME: double [[X:%.*]], i32 [[EXP:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call double @llvm.ldexp.f64.i32(double [[X]], i32 [[EXP]])
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @scalbn(double %x, i32 %exp) memory(none)
+  ret double %r
+}
+
+; Cover the long double variant.
+
+define fp128 @scalbnl_f128(fp128 %x, i32 %exp) {
+; CHECK-LABEL: define fp128 @scalbnl_f128(
+; CHECK-SAME: fp128 [[X:%.*]], i32 [[EXP:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call fp128 @llvm.ldexp.f128.i32(fp128 [[X]], i32 [[EXP]])
+; CHECK-NEXT:    ret fp128 [[R]]
+;
+  %r = call fp128 @scalbnl(fp128 %x, i32 %exp) memory(none)
+  ret fp128 %r
+}
+
+; Calls that may set errno must remain libcalls.
+
+define double @scalbn_errno(double %x, i32 %exp) {
+; CHECK-LABEL: define double @scalbn_errno(
+; CHECK-SAME: double [[X:%.*]], i32 [[EXP:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call double @scalbn(double [[X]], i32 [[EXP]])
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @scalbn(double %x, i32 %exp)
+  ret double %r
+}
+
+; Strict floating-point calls must remain libcalls even when errno is disabled.
+
+define double @scalbn_strictfp(double %x, i32 %exp) strictfp {
+; CHECK-LABEL: define double @scalbn_strictfp(
+; CHECK-SAME: double [[X:%.*]], i32 [[EXP:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    [[R:%.*]] = call double @scalbn(double [[X]], i32 [[EXP]]) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @scalbn(double %x, i32 %exp) strictfp memory(none)
+  ret double %r
+}
+
+; A nobuiltin call must not be recognized as the standard scalbn function.
+
+define double @scalbn_nobuiltin(double %x, i32 %exp) {
+; CHECK-LABEL: define double @scalbn_nobuiltin(
+; CHECK-SAME: double [[X:%.*]], i32 [[EXP:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call double @scalbn(double [[X]], i32 [[EXP]]) #[[ATTR3:[0-9]+]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %r = call double @scalbn(double %x, i32 %exp) nobuiltin memory(none)
+  ret double %r
+}
----------------
ChrisLee02 wrote:

https://github.com/llvm/llvm-project/commit/844a710e8806c438afee90315a685d16ee351d3c

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


More information about the llvm-commits mailing list