Skip to content

[ConstantFold] Fold ilogb and ilogbf when the input parameter is a constant value. #113014

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 20, 2024
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
10 changes: 9 additions & 1 deletion llvm/lib/Analysis/ConstantFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1677,6 +1677,8 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
return Name == "fabs" || Name == "fabsf" ||
Name == "floor" || Name == "floorf" ||
Name == "fmod" || Name == "fmodf";
case 'i':
return Name == "ilogb" || Name == "ilogbf";
case 'l':
return Name == "log" || Name == "logf" || Name == "logl" ||
Name == "log2" || Name == "log2f" || Name == "log10" ||
Expand Down Expand Up @@ -2131,7 +2133,8 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
}
#endif

if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy() &&
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 just handle this case before here, or just delete the whole check.

This function could use some cleanup. Why isn't this using a switch over the intrinsic ID?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably should just handle this case before here, or just delete the whole check.

It appears that the check is necessary to guard certain types, such as vector or fp128 types.

!Ty->isIntegerTy())
return nullptr;

// Use internal versions of these intrinsics.
Expand Down Expand Up @@ -2391,6 +2394,11 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
// TODO: What about hosts that lack a C99 library?
return ConstantFoldFP(log10, APF, Ty);
break;
case LibFunc_ilogb:
case LibFunc_ilogbf:
if (!APF.isZero() && TLI->has(Func))
return ConstantInt::get(Ty, ilogb(APF), true);
break;
case LibFunc_logb:
case LibFunc_logbf:
if (!APF.isZero() && TLI->has(Func))
Expand Down
203 changes: 203 additions & 0 deletions llvm/test/Transforms/InstCombine/ilogb.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -passes=instcombine -S | FileCheck %s

define i32 @ilogbf_const1() {
; CHECK-LABEL: define i32 @ilogbf_const1() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 7.000000e+00)
; CHECK-NEXT: ret i32 2
;
%r = call i32 @ilogbf(float 7.000000e+00)
ret i32 %r
}

define i32 @ilogb_const1() {
; CHECK-LABEL: define i32 @ilogb_const1() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -7.000000e+00)
; CHECK-NEXT: ret i32 2
;
%r = call i32 @ilogb(double -7.000000e+00)
ret i32 %r
}

define i32 @ilogbf_const2() {
; CHECK-LABEL: define i32 @ilogbf_const2() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 5.000000e-01)
; CHECK-NEXT: ret i32 -1
;
%r = call i32 @ilogbf(float 5.000000e-01)
ret i32 %r
}

define i32 @ilogb_const2() {
; CHECK-LABEL: define i32 @ilogb_const2() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -5.000000e-01)
; CHECK-NEXT: ret i32 -1
;
%r = call i32 @ilogb(double -5.000000e-01)
ret i32 %r
}

define i32 @ilogbf_zero() {
; CHECK-LABEL: define i32 @ilogbf_zero() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0.000000e+00)
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogbf(float 0.000000e+00)
ret i32 %r
}

define i32 @ilogb_zero() {
; CHECK-LABEL: define i32 @ilogb_zero() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0.000000e+00)
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogb(double 0.000000e+00)
ret i32 %r
}

define i32 @ilogbf_neg_zero() {
; CHECK-LABEL: define i32 @ilogbf_neg_zero() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float -0.000000e+00)
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogbf(float -0.000000e+00)
ret i32 %r
}

define i32 @ilogb_neg_zero() {
; CHECK-LABEL: define i32 @ilogb_neg_zero() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -0.000000e+00)
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogb(double -0.000000e+00)
ret i32 %r
}

define i32 @ilogbf_inf() {
; CHECK-LABEL: define i32 @ilogbf_inf() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF0000000000000)
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogbf(float 0x7FF0000000000000)
ret i32 %r
}

define i32 @ilogb_inf() {
; CHECK-LABEL: define i32 @ilogb_inf() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF0000000000000)
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogb(double 0x7FF0000000000000)
ret i32 %r
}

define i32 @ilogbf_nan() {
; CHECK-LABEL: define i32 @ilogbf_nan() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF8000000000000)
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogbf(float 0x7FF8000000000000)
ret i32 %r
}

define i32 @ilogb_nan() {
; CHECK-LABEL: define i32 @ilogb_nan() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF8000000000000)
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogb(double 0x7FF8000000000000)
ret i32 %r
}

define i32 @ilogbf_zero_readnone() {
; CHECK-LABEL: define i32 @ilogbf_zero_readnone() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0.000000e+00) #[[ATTR0:[0-9]+]]
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogbf(float 0.000000e+00) readnone
ret i32 %r
}

define i32 @ilogb_zero_readnone() {
; CHECK-LABEL: define i32 @ilogb_zero_readnone() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0.000000e+00) #[[ATTR0]]
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogb(double 0.000000e+00) readnone
ret i32 %r
}

define i32 @ilogbf_neg_zero_readnone() {
; CHECK-LABEL: define i32 @ilogbf_neg_zero_readnone() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float -0.000000e+00) #[[ATTR0]]
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogbf(float -0.000000e+00) readnone
ret i32 %r
}

define i32 @ilogb_neg_zero_readnone() {
; CHECK-LABEL: define i32 @ilogb_neg_zero_readnone() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -0.000000e+00) #[[ATTR0]]
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogb(double -0.000000e+00) readnone
ret i32 %r
}

define i32 @ilogbf_inf_readnone() {
; CHECK-LABEL: define i32 @ilogbf_inf_readnone() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF0000000000000) #[[ATTR0]]
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogbf(float 0x7FF0000000000000) readnone
ret i32 %r
}

define i32 @ilogb_inf_readnone() {
; CHECK-LABEL: define i32 @ilogb_inf_readnone() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF0000000000000) #[[ATTR0]]
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogb(double 0x7FF0000000000000) readnone
ret i32 %r
}

define i32 @ilogbf_nan_readnone() {
; CHECK-LABEL: define i32 @ilogbf_nan_readnone() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF8000000000000) #[[ATTR0]]
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogbf(float 0x7FF8000000000000) readnone
ret i32 %r
}

define i32 @ilogb_nan_readnone() {
; CHECK-LABEL: define i32 @ilogb_nan_readnone() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF8000000000000) #[[ATTR0]]
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogb(double 0x7FF8000000000000) readnone
ret i32 %r
}

define i32 @ilogbf_poison() {
; CHECK-LABEL: define i32 @ilogbf_poison() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float poison)
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogbf(float poison)
ret i32 %r
}

define i32 @ilogb_poison() {
; CHECK-LABEL: define i32 @ilogb_poison() {
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double poison)
; CHECK-NEXT: ret i32 [[R]]
;
%r = call i32 @ilogb(double poison)
ret i32 %r
}

declare i32 @ilogbf(float)
declare i32 @ilogb(double)
Loading