David Green 5184d763c7
[InstCombine] Convert @log to @llvm.log if the input is known positive. (#111428)
Similar to 112aac4e8961b9626bb84f36deeaa5a674f03f5a, this converts log
libcalls to llvm.log.f64 intrinsics if we know they do not set errno, as
the input is not zero and not negative. As log will produce errno if the
input is 0 (returning -inf) or if the input is negative (returning nan),
we also perform the conversion when we have noinf and nonan.
2024-10-10 09:54:25 +01:00

356 lines
11 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
define float @test_logf_pos(float %f) {
; CHECK-LABEL: define float @test_logf_pos(
; CHECK-SAME: float [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt float [[F]], 0.000000e+00
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call float @llvm.log.f32(float [[F]])
; CHECK-NEXT: ret float [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret float 0.000000e+00
;
entry:
%isinf = fcmp ole float %f, 0x0000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call float @logf(float %f)
ret float %call
return:
ret float 0.0
}
define double @test_log_pos(double %f) {
; CHECK-LABEL: define double @test_log_pos(
; CHECK-SAME: double [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt double [[F]], 0.000000e+00
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call double @llvm.log.f64(double [[F]])
; CHECK-NEXT: ret double [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret double 0.000000e+00
;
entry:
%isinf = fcmp ole double %f, 0x0000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call double @log(double %f)
ret double %call
return:
ret double 0.0
}
define fp128 @test_logl_pos(fp128 %f) {
; CHECK-LABEL: define fp128 @test_logl_pos(
; CHECK-SAME: fp128 [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt fp128 [[F]], 0xL00000000000000000000000000000000
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call fp128 @llvm.log.f128(fp128 [[F]])
; CHECK-NEXT: ret fp128 [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret fp128 0xL00000000000000000000000000000000
;
entry:
%isinf = fcmp ole fp128 %f, 0xL00000000000000000000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call fp128 @logl(fp128 %f)
ret fp128 %call
return:
ret fp128 0xL00000000000000000000000000000000
}
define float @test_log10f_pos(float %f) {
; CHECK-LABEL: define float @test_log10f_pos(
; CHECK-SAME: float [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt float [[F]], 0.000000e+00
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call float @llvm.log10.f32(float [[F]])
; CHECK-NEXT: ret float [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret float 0.000000e+00
;
entry:
%isinf = fcmp ole float %f, 0x0000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call float @log10f(float %f)
ret float %call
return:
ret float 0.0
}
define double @test_log10_pos(double %f) {
; CHECK-LABEL: define double @test_log10_pos(
; CHECK-SAME: double [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt double [[F]], 0.000000e+00
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call double @llvm.log10.f64(double [[F]])
; CHECK-NEXT: ret double [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret double 0.000000e+00
;
entry:
%isinf = fcmp ole double %f, 0x0000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call double @log10(double %f)
ret double %call
return:
ret double 0.0
}
define fp128 @test_log10l_pos(fp128 %f) {
; CHECK-LABEL: define fp128 @test_log10l_pos(
; CHECK-SAME: fp128 [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt fp128 [[F]], 0xL00000000000000000000000000000000
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call fp128 @llvm.log10.f128(fp128 [[F]])
; CHECK-NEXT: ret fp128 [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret fp128 0xL00000000000000000000000000000000
;
entry:
%isinf = fcmp ole fp128 %f, 0xL00000000000000000000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call fp128 @log10l(fp128 %f)
ret fp128 %call
return:
ret fp128 0xL00000000000000000000000000000000
}
define float @test_log2f_pos(float %f) {
; CHECK-LABEL: define float @test_log2f_pos(
; CHECK-SAME: float [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt float [[F]], 0.000000e+00
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call float @llvm.log2.f32(float [[F]])
; CHECK-NEXT: ret float [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret float 0.000000e+00
;
entry:
%isinf = fcmp ole float %f, 0x0000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call float @log2f(float %f)
ret float %call
return:
ret float 0.0
}
define double @test_log2_pos(double %f) {
; CHECK-LABEL: define double @test_log2_pos(
; CHECK-SAME: double [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt double [[F]], 0.000000e+00
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call double @llvm.log2.f64(double [[F]])
; CHECK-NEXT: ret double [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret double 0.000000e+00
;
entry:
%isinf = fcmp ole double %f, 0x0000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call double @log2(double %f)
ret double %call
return:
ret double 0.0
}
define fp128 @test_log2l_pos(fp128 %f) {
; CHECK-LABEL: define fp128 @test_log2l_pos(
; CHECK-SAME: fp128 [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt fp128 [[F]], 0xL00000000000000000000000000000000
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call fp128 @llvm.log2.f128(fp128 [[F]])
; CHECK-NEXT: ret fp128 [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret fp128 0xL00000000000000000000000000000000
;
entry:
%isinf = fcmp ole fp128 %f, 0xL00000000000000000000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call fp128 @log2l(fp128 %f)
ret fp128 %call
return:
ret fp128 0xL00000000000000000000000000000000
}
define double @test_logb_pos(double %f) {
; CHECK-LABEL: define double @test_logb_pos(
; CHECK-SAME: double [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt double [[F]], 0.000000e+00
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call double @logb(double [[F]])
; CHECK-NEXT: ret double [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret double 0.000000e+00
;
entry:
%isinf = fcmp ole double %f, 0x0000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call double @logb(double %f)
ret double %call
return:
ret double 0.0
}
define double @test_log1p_pos(double %f) {
; CHECK-LABEL: define double @test_log1p_pos(
; CHECK-SAME: double [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt double [[F]], 0.000000e+00
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call double @log1p(double [[F]])
; CHECK-NEXT: ret double [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret double 0.000000e+00
;
entry:
%isinf = fcmp ole double %f, 0x0000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call double @log1p(double %f)
ret double %call
return:
ret double 0.0
}
define float @metadata(float %f) {
; CHECK-LABEL: define float @metadata(
; CHECK-SAME: float [[F:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt float [[F]], 0.000000e+00
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call float @llvm.log.f32(float [[F]]), !fpmath [[META0:![0-9]+]]
; CHECK-NEXT: ret float [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret float 0.000000e+00
;
entry:
%isinf = fcmp ole float %f, 0x0000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call float @logf(float %f), !fpmath !0
ret float %call
return:
ret float 0.0
}
!0 = !{ float 2.5 }
define float @test_logf_pos_denormalpreserve(float %f) "denormal-fp-math"="preserve-sign,preserve-sign" {
; CHECK-LABEL: define float @test_logf_pos_denormalpreserve(
; CHECK-SAME: float [[F:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt float [[F]], 0.000000e+00
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call float @logf(float [[F]])
; CHECK-NEXT: ret float [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret float 0.000000e+00
;
entry:
%isinf = fcmp ole float %f, 0x0000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call float @logf(float %f)
ret float %call
return:
ret float 0.0
}
define float @test_logf_pos_denormaldynamic(float %f) "denormal-fp-math"="dynamic,dynamic" {
; CHECK-LABEL: define float @test_logf_pos_denormaldynamic(
; CHECK-SAME: float [[F:%.*]]) #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ISINF:%.*]] = fcmp ugt float [[F]], 0.000000e+00
; CHECK-NEXT: br i1 [[ISINF]], label %[[IF_END:.*]], label %[[RETURN:.*]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[CALL:%.*]] = tail call float @logf(float [[F]])
; CHECK-NEXT: ret float [[CALL]]
; CHECK: [[RETURN]]:
; CHECK-NEXT: ret float 0.000000e+00
;
entry:
%isinf = fcmp ole float %f, 0x0000000000000000
br i1 %isinf, label %return, label %if.end
if.end:
%call = tail call float @logf(float %f)
ret float %call
return:
ret float 0.0
}
declare double @log(double)
declare float @logf(float)
declare fp128 @logl(fp128)
declare double @log10(double)
declare float @log10f(float)
declare fp128 @log10l(fp128)
declare double @log2(double)
declare float @log2f(float)
declare fp128 @log2l(fp128)
declare double @logb(double)
declare double @log1p(double)
;.
; CHECK: [[META0]] = !{float 2.500000e+00}
;.