diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 962880f68f076..6c52091cd5d75 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -2754,27 +2754,28 @@ static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty, ((Mask & fcPosInf) && Op1V.isPosInfinity()); return ConstantInt::get(Ty, Result); } + case Intrinsic::powi: { + int Exp = static_cast(Op2C->getSExtValue()); + switch (Ty->getTypeID()) { + case Type::HalfTyID: + case Type::FloatTyID: { + APFloat Res(std::pow(Op1V.convertToFloat(), Exp)); + if (Ty->isHalfTy()) { + bool Unused; + Res.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, + &Unused); + } + return ConstantFP::get(Ty->getContext(), Res); + } + case Type::DoubleTyID: + return ConstantFP::get(Ty, std::pow(Op1V.convertToDouble(), Exp)); + default: + return nullptr; + } + } default: break; } - - if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy()) - return nullptr; - if (IntrinsicID == Intrinsic::powi && Ty->isHalfTy()) - return ConstantFP::get( - Ty->getContext(), - APFloat((float)std::pow((float)Op1V.convertToDouble(), - (int)Op2C->getZExtValue()))); - if (IntrinsicID == Intrinsic::powi && Ty->isFloatTy()) - return ConstantFP::get( - Ty->getContext(), - APFloat((float)std::pow((float)Op1V.convertToDouble(), - (int)Op2C->getZExtValue()))); - if (IntrinsicID == Intrinsic::powi && Ty->isDoubleTy()) - return ConstantFP::get( - Ty->getContext(), - APFloat((double)std::pow(Op1V.convertToDouble(), - (int)Op2C->getZExtValue()))); } return nullptr; } diff --git a/llvm/test/Transforms/EarlyCSE/math-2.ll b/llvm/test/Transforms/EarlyCSE/math-2.ll index d9f7c619fa013..60a2f19084c83 100644 --- a/llvm/test/Transforms/EarlyCSE/math-2.ll +++ b/llvm/test/Transforms/EarlyCSE/math-2.ll @@ -98,4 +98,14 @@ define double @i_powi() { ret double %res } +; Make sure that the type is correct after constant folding + +define half @pr98665() { +; CHECK-LABEL: @pr98665( +; CHECK-NEXT: ret half 0xH3C00 +; + %x = call half @llvm.powi.f16.i32(half 0xH3C00, i32 1) + ret half %x +} + attributes #0 = { nofree nounwind willreturn }