Index: llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp @@ -449,7 +449,10 @@ break; } - case Intrinsic::amdgcn_log: { + case Intrinsic::amdgcn_log: + case Intrinsic::amdgcn_exp2: { + const bool IsLog = IID == Intrinsic::amdgcn_log; + const bool IsExp = IID == Intrinsic::amdgcn_exp2; Value *Src = II.getArgOperand(0); Type *Ty = II.getType(); @@ -460,8 +463,16 @@ return IC.replaceInstUsesWith(II, ConstantFP::getNaN(Ty)); if (ConstantFP *C = dyn_cast(Src)) { - if (C->isInfinity() && !C->isNegative()) - return IC.replaceInstUsesWith(II, C); + if (C->isInfinity()) { + // exp2(+inf) -> +inf + // log2(+inf) -> +inf + if (!C->isNegative()) + return IC.replaceInstUsesWith(II, C); + + // exp2(-inf) -> 0 + if (IsExp && C->isNegative()) + return IC.replaceInstUsesWith(II, ConstantFP::getZero(Ty)); + } if (II.isStrictFP()) break; @@ -472,10 +483,13 @@ } // 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->isZero() || (C->getValue().isDenormal() && Ty->isFloatTy())) { + Constant *FoldedValue = IsLog ? ConstantFP::getInfinity(Ty, true) + : ConstantFP::get(Ty, 1.0); + return IC.replaceInstUsesWith(II, FoldedValue); + } - if (C->isNegative()) + if (IsLog && C->isNegative()) return IC.replaceInstUsesWith(II, ConstantFP::getNaN(Ty)); // TODO: Full constant folding matching hardware behavior. Index: llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll =================================================================== --- llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll +++ llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll @@ -5922,8 +5922,7 @@ define float @test_constant_fold_exp2_f32_undef() { ; CHECK-LABEL: @test_constant_fold_exp2_f32_undef( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float undef) -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %val = call float @llvm.amdgcn.exp2.f32(float undef) ret float %val @@ -5931,8 +5930,7 @@ define float @test_constant_fold_exp2_f32_poison() { ; CHECK-LABEL: @test_constant_fold_exp2_f32_poison( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float poison) -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float poison ; %val = call float @llvm.amdgcn.exp2.f32(float poison) ret float %val @@ -5940,8 +5938,7 @@ define float @test_constant_fold_exp2_f32_p0() { ; CHECK-LABEL: @test_constant_fold_exp2_f32_p0( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float 0.000000e+00) -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float 1.000000e+00 ; %val = call float @llvm.amdgcn.exp2.f32(float 0.0) ret float %val @@ -5949,8 +5946,7 @@ define float @test_constant_fold_exp2_f32_n0() { ; CHECK-LABEL: @test_constant_fold_exp2_f32_n0( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float -0.000000e+00) -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float 1.000000e+00 ; %val = call float @llvm.amdgcn.exp2.f32(float -0.0) ret float %val @@ -6012,8 +6008,7 @@ define float @test_constant_fold_exp2_f32_subnormal() { ; CHECK-LABEL: @test_constant_fold_exp2_f32_subnormal( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float 0x380FFFFFC0000000) -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float 1.000000e+00 ; %val = call float @llvm.amdgcn.exp2.f32(float 0x380FFFFFC0000000) ret float %val @@ -6021,8 +6016,7 @@ define float @test_constant_fold_exp2_f32_negsubnormal() { ; CHECK-LABEL: @test_constant_fold_exp2_f32_negsubnormal( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float 0xB80FFFFFC0000000) -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float 1.000000e+00 ; %val = call float @llvm.amdgcn.exp2.f32(float 0xB80FFFFFC0000000) ret float %val @@ -6030,8 +6024,7 @@ define float @test_constant_fold_exp2_f32_pinf() { ; CHECK-LABEL: @test_constant_fold_exp2_f32_pinf( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float 0x7FF0000000000000) -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float 0x7FF0000000000000 ; %val = call float @llvm.amdgcn.exp2.f32(float 0x7FF0000000000000) ret float %val @@ -6039,8 +6032,7 @@ define float @test_constant_fold_exp2_f32_ninf() { ; CHECK-LABEL: @test_constant_fold_exp2_f32_ninf( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float 0xFFF0000000000000) -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float 0.000000e+00 ; %val = call float @llvm.amdgcn.exp2.f32(float 0xFFF0000000000000) ret float %val @@ -6066,8 +6058,7 @@ define float @test_constant_fold_exp2_f32_qnan() { ; CHECK-LABEL: @test_constant_fold_exp2_f32_qnan( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float 0x7FF8000000000000) -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %val = call float @llvm.amdgcn.exp2.f32(float 0x7FF8000000000000) ret float %val @@ -6075,8 +6066,7 @@ define float @test_constant_fold_exp2_f32_snan() { ; CHECK-LABEL: @test_constant_fold_exp2_f32_snan( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float 0x7FF0000020000000) -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float 0x7FF8000020000000 ; %val = call float @llvm.amdgcn.exp2.f32(float 0x7FF0000020000000) ret float %val @@ -6084,8 +6074,7 @@ define half @test_constant_fold_exp2_f16_p0() { ; CHECK-LABEL: @test_constant_fold_exp2_f16_p0( -; CHECK-NEXT: [[VAL:%.*]] = call half @llvm.amdgcn.exp2.f16(half 0xH0000) -; CHECK-NEXT: ret half [[VAL]] +; CHECK-NEXT: ret half 0xH3C00 ; %val = call half @llvm.amdgcn.exp2.f16(half 0.0) ret half %val @@ -6174,8 +6163,7 @@ define float @test_constant_fold_exp2_f32_pinf_strictfp() strictfp { ; CHECK-LABEL: @test_constant_fold_exp2_f32_pinf_strictfp( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float 0x7FF0000000000000) #[[ATTR16]] -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float 0x7FF0000000000000 ; %val = call float @llvm.amdgcn.exp2.f32(float 0x7FF0000000000000) strictfp ret float %val @@ -6183,8 +6171,7 @@ define float @test_constant_fold_exp2_f32_ninf_strictfp() strictfp { ; CHECK-LABEL: @test_constant_fold_exp2_f32_ninf_strictfp( -; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.amdgcn.exp2.f32(float 0xFFF0000000000000) #[[ATTR16]] -; CHECK-NEXT: ret float [[VAL]] +; CHECK-NEXT: ret float 0.000000e+00 ; %val = call float @llvm.amdgcn.exp2.f32(float 0xFFF0000000000000) strictfp ret float %val