Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4136,6 +4136,11 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI, IRBuilderBase &Builder) {
return optimizeMemCpy(CI, Builder);
case Intrinsic::memmove:
return optimizeMemMove(CI, Builder);
case Intrinsic::sin:
case Intrinsic::cos:
if (UnsafeFPShrink)
return optimizeUnaryDoubleFP(CI, Builder, TLI, /*isPrecise=*/true);
return nullptr;
default:
return nullptr;
}
Expand Down
28 changes: 18 additions & 10 deletions llvm/test/Transforms/InstCombine/cos-1.ll
Original file line number Diff line number Diff line change
Expand Up @@ -435,11 +435,15 @@ define float @unary_negated_and_shrinkable_libcall(float %f) {
; TODO: It was ok to shrink the libcall, so the intrinsic should shrink too?

define float @negated_and_shrinkable_intrinsic(float %f) {
; ANY-LABEL: @negated_and_shrinkable_intrinsic(
; ANY-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double
; ANY-NEXT: [[COS:%.*]] = call double @llvm.cos.f64(double [[CONV1]])
; ANY-NEXT: [[CONV2:%.*]] = fptrunc double [[COS]] to float
; ANY-NEXT: ret float [[CONV2]]
; NO-FLOAT-SHRINK-LABEL: @negated_and_shrinkable_intrinsic(
; NO-FLOAT-SHRINK-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double
; NO-FLOAT-SHRINK-NEXT: [[COS:%.*]] = call double @llvm.cos.f64(double [[CONV1]])
; NO-FLOAT-SHRINK-NEXT: [[CONV2:%.*]] = fptrunc double [[COS]] to float
; NO-FLOAT-SHRINK-NEXT: ret float [[CONV2]]
;
; DO-FLOAT-SHRINK-LABEL: @negated_and_shrinkable_intrinsic(
; DO-FLOAT-SHRINK-NEXT: [[COS:%.*]] = call float @llvm.cos.f32(float [[F:%.*]])
; DO-FLOAT-SHRINK-NEXT: ret float [[COS]]
;
%conv1 = fpext float %f to double
%neg = fsub double -0.0, %conv1
Expand All @@ -449,11 +453,15 @@ define float @negated_and_shrinkable_intrinsic(float %f) {
}

define float @unary_negated_and_shrinkable_intrinsic(float %f) {
; ANY-LABEL: @unary_negated_and_shrinkable_intrinsic(
; ANY-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double
; ANY-NEXT: [[COS:%.*]] = call double @llvm.cos.f64(double [[CONV1]])
; ANY-NEXT: [[CONV2:%.*]] = fptrunc double [[COS]] to float
; ANY-NEXT: ret float [[CONV2]]
; NO-FLOAT-SHRINK-LABEL: @unary_negated_and_shrinkable_intrinsic(
; NO-FLOAT-SHRINK-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double
; NO-FLOAT-SHRINK-NEXT: [[COS:%.*]] = call double @llvm.cos.f64(double [[CONV1]])
; NO-FLOAT-SHRINK-NEXT: [[CONV2:%.*]] = fptrunc double [[COS]] to float
; NO-FLOAT-SHRINK-NEXT: ret float [[CONV2]]
;
; DO-FLOAT-SHRINK-LABEL: @unary_negated_and_shrinkable_intrinsic(
; DO-FLOAT-SHRINK-NEXT: [[COS:%.*]] = call float @llvm.cos.f32(float [[F:%.*]])
; DO-FLOAT-SHRINK-NEXT: ret float [[COS]]
;
%conv1 = fpext float %f to double
%neg = fneg double %conv1
Expand Down
69 changes: 69 additions & 0 deletions llvm/test/Transforms/InstCombine/simplify-intrinsics.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -S | FileCheck %s --check-prefixes=ANY,NO-FLOAT-SHRINK
; RUN: opt < %s -passes=instcombine -enable-double-float-shrink -S | FileCheck %s --check-prefixes=ANY,DO-FLOAT-SHRINK

declare double @llvm.cos.f64(double)
declare float @llvm.cos.f32(float)

declare double @llvm.sin.f64(double)
declare float @llvm.sin.f32(float)

; cos -> cosf

define float @cos_no_fastmath(float %f) {
; NO-FLOAT-SHRINK-LABEL: @cos_no_fastmath(
; NO-FLOAT-SHRINK-NEXT: [[D:%.*]] = fpext float [[F:%.*]] to double
; NO-FLOAT-SHRINK-NEXT: [[RESULT:%.*]] = call double @llvm.cos.f64(double [[D]])
; NO-FLOAT-SHRINK-NEXT: [[TRUNCATED_RESULT:%.*]] = fptrunc double [[RESULT]] to float
; NO-FLOAT-SHRINK-NEXT: ret float [[TRUNCATED_RESULT]]
;
; DO-FLOAT-SHRINK-LABEL: @cos_no_fastmath(
; DO-FLOAT-SHRINK-NEXT: [[TMP1:%.*]] = call float @llvm.cos.f32(float [[F:%.*]])
; DO-FLOAT-SHRINK-NEXT: ret float [[TMP1]]
;
%d = fpext float %f to double
%result = call double @llvm.cos.f64(double %d)
%truncated_result = fptrunc double %result to float
ret float %truncated_result
}

define float @cos_fastmath(float %f) {
; ANY-LABEL: @cos_fastmath(
; ANY-NEXT: [[TMP1:%.*]] = call fast float @llvm.cos.f32(float [[F:%.*]])
; ANY-NEXT: ret float [[TMP1]]
;
%d = fpext float %f to double
%result = call fast double @llvm.cos.f64(double %d)
%truncated_result = fptrunc double %result to float
ret float %truncated_result
}

; sin -> sinf

define float @sin_no_fastmath(float %f) {
; NO-FLOAT-SHRINK-LABEL: @sin_no_fastmath(
; NO-FLOAT-SHRINK-NEXT: [[D:%.*]] = fpext float [[F:%.*]] to double
; NO-FLOAT-SHRINK-NEXT: [[RESULT:%.*]] = call double @llvm.sin.f64(double [[D]])
; NO-FLOAT-SHRINK-NEXT: [[TRUNCATED_RESULT:%.*]] = fptrunc double [[RESULT]] to float
; NO-FLOAT-SHRINK-NEXT: ret float [[TRUNCATED_RESULT]]
;
; DO-FLOAT-SHRINK-LABEL: @sin_no_fastmath(
; DO-FLOAT-SHRINK-NEXT: [[TMP1:%.*]] = call float @llvm.sin.f32(float [[F:%.*]])
; DO-FLOAT-SHRINK-NEXT: ret float [[TMP1]]
;
%d = fpext float %f to double
%result = call double @llvm.sin.f64(double %d)
%truncated_result = fptrunc double %result to float
ret float %truncated_result
}

define float @sin_fastmath(float %f) {
; ANY-LABEL: @sin_fastmath(
; ANY-NEXT: [[TMP1:%.*]] = call fast float @llvm.sin.f32(float [[F:%.*]])
; ANY-NEXT: ret float [[TMP1]]
;
%d = fpext float %f to double
%result = call fast double @llvm.sin.f64(double %d)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this just valid with all fast-math flags, or some subset?

Copy link
Contributor Author

@guy-david guy-david May 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing optimization for libcalls requires all fast-math flags to be present.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should fix that, this shouldn't require all of them (in particular nsz or contract)

%truncated_result = fptrunc double %result to float
ret float %truncated_result
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also test vector case

Copy link
Contributor Author

@guy-david guy-david May 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work, I think because of this check:

if (!CI->getType()->isDoubleTy() || !CalleeFn)

Let's build up on it in a subsequent PR.

Loading