break;
}
+ case Intrinsic::amdgcn_log: {
+ Value *Src = II.getArgOperand(0);
+ Type *Ty = II.getType();
+
+ if (isa<PoisonValue>(Src))
+ return IC.replaceInstUsesWith(II, Src);
+
+ if (IC.getSimplifyQuery().isUndefValue(Src))
+ return IC.replaceInstUsesWith(II, ConstantFP::getNaN(Ty));
+
+ if (ConstantFP *C = dyn_cast<ConstantFP>(Src)) {
+ if (C->isInfinity() && !C->isNegative())
+ return IC.replaceInstUsesWith(II, C);
+
+ if (II.isStrictFP())
+ break;
+
+ if (C->isNaN()) {
+ Constant *Quieted = ConstantFP::get(Ty, C->getValue().makeQuiet());
+ return IC.replaceInstUsesWith(II, Quieted);
+ }
+
+ // f32 instruction doesn't handle denormals, f16 does.
+ if (C->isZero() || (C->getValue().isDenormal() && Ty->isFloatTy()))
+ return IC.replaceInstUsesWith(II, ConstantFP::getInfinity(Ty, true));
+
+ if (C->isNegative())
+ return IC.replaceInstUsesWith(II, ConstantFP::getNaN(Ty));
+
+ // TODO: Full constant folding matching hardware behavior.
+ }
+
+ break;
+ }
case Intrinsic::amdgcn_frexp_mant:
case Intrinsic::amdgcn_frexp_exp: {
Value *Src = II.getArgOperand(0);
define float @test_constant_fold_log_f32_undef() {
; CHECK-LABEL: @test_constant_fold_log_f32_undef(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float undef)
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float 0x7FF8000000000000
;
%val = call float @llvm.amdgcn.log.f32(float undef)
ret float %val
define float @test_constant_fold_log_f32_poison() {
; CHECK-LABEL: @test_constant_fold_log_f32_poison(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float poison)
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float poison
;
%val = call float @llvm.amdgcn.log.f32(float poison)
ret float %val
define float @test_constant_fold_log_f32_p0() {
; CHECK-LABEL: @test_constant_fold_log_f32_p0(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float 0.000000e+00)
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float 0xFFF0000000000000
;
%val = call float @llvm.amdgcn.log.f32(float 0.0)
ret float %val
define float @test_constant_fold_log_f32_n0() {
; CHECK-LABEL: @test_constant_fold_log_f32_n0(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float -0.000000e+00)
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float 0xFFF0000000000000
;
%val = call float @llvm.amdgcn.log.f32(float -0.0)
ret float %val
define float @test_constant_fold_log_f32_subnormal() {
; CHECK-LABEL: @test_constant_fold_log_f32_subnormal(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float 0x380FFFFFC0000000)
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float 0xFFF0000000000000
;
%val = call float @llvm.amdgcn.log.f32(float 0x380FFFFFC0000000)
ret float %val
define float @test_constant_fold_log_f32_negsubnormal() {
; CHECK-LABEL: @test_constant_fold_log_f32_negsubnormal(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float 0xB80FFFFFC0000000)
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float 0xFFF0000000000000
;
%val = call float @llvm.amdgcn.log.f32(float 0xB80FFFFFC0000000)
ret float %val
define float @test_constant_fold_log_f32_pinf() {
; CHECK-LABEL: @test_constant_fold_log_f32_pinf(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float 0x7FF0000000000000)
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float 0x7FF0000000000000
;
%val = call float @llvm.amdgcn.log.f32(float 0x7FF0000000000000)
ret float %val
define float @test_constant_fold_log_f32_ninf() {
; CHECK-LABEL: @test_constant_fold_log_f32_ninf(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float 0xFFF0000000000000)
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float 0x7FF8000000000000
;
%val = call float @llvm.amdgcn.log.f32(float 0xFFF0000000000000)
ret float %val
define float @test_constant_fold_log_f32_neg10() {
; CHECK-LABEL: @test_constant_fold_log_f32_neg10(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float -1.000000e+01)
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float 0x7FF8000000000000
;
%val = call float @llvm.amdgcn.log.f32(float -10.0)
ret float %val
define float @test_constant_fold_log_f32_qnan() {
; CHECK-LABEL: @test_constant_fold_log_f32_qnan(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float 0x7FF8000000000000)
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float 0x7FF8000000000000
;
%val = call float @llvm.amdgcn.log.f32(float 0x7FF8000000000000)
ret float %val
define float @test_constant_fold_log_f32_snan() {
; CHECK-LABEL: @test_constant_fold_log_f32_snan(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float 0x7FF0000020000000)
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float 0x7FF8000020000000
;
%val = call float @llvm.amdgcn.log.f32(float 0x7FF0000020000000)
ret float %val
define half @test_constant_fold_log_f16_p0() {
; CHECK-LABEL: @test_constant_fold_log_f16_p0(
-; CHECK-NEXT: [[VAL:%.*]] = call half @llvm.amdgcn.log.f16(half 0xH0000)
-; CHECK-NEXT: ret half [[VAL]]
+; CHECK-NEXT: ret half 0xHFC00
;
%val = call half @llvm.amdgcn.log.f16(half 0.0)
ret half %val
define half @test_constant_fold_log_f16_neg10() {
; CHECK-LABEL: @test_constant_fold_log_f16_neg10(
-; CHECK-NEXT: [[VAL:%.*]] = call half @llvm.amdgcn.log.f16(half 0xHC900)
-; CHECK-NEXT: ret half [[VAL]]
+; CHECK-NEXT: ret half 0xH7E00
;
%val = call half @llvm.amdgcn.log.f16(half -10.0)
ret half %val
define float @test_constant_fold_log_f32_pinf_strictfp() strictfp {
; CHECK-LABEL: @test_constant_fold_log_f32_pinf_strictfp(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.log.f32(float 0x7FF0000000000000) #[[ATTR16]]
-; CHECK-NEXT: ret float [[VAL]]
+; CHECK-NEXT: ret float 0x7FF0000000000000
;
%val = call float @llvm.amdgcn.log.f32(float 0x7FF0000000000000) strictfp
ret float %val
define half @test_constant_fold_log_f16_neg_denorm() {
; CHECK-LABEL: @test_constant_fold_log_f16_neg_denorm(
-; CHECK-NEXT: [[VAL:%.*]] = call half @llvm.amdgcn.log.f16(half 0xH83FF)
-; CHECK-NEXT: ret half [[VAL]]
+; CHECK-NEXT: ret half 0xH7E00
;
%val = call half @llvm.amdgcn.log.f16(half 0xH83ff)
ret half %val