Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
11 changes: 7 additions & 4 deletions 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,11 +2133,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
}
#endif

if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
return nullptr;

// Use internal versions of these intrinsics.

if (IntrinsicID == Intrinsic::nearbyint || IntrinsicID == Intrinsic::rint) {
U.roundToIntegral(APFloat::rmNearestTiesToEven);
return ConstantFP::get(Ty->getContext(), U);
Expand Down Expand Up @@ -2391,6 +2389,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