Index: llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp +++ llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp @@ -567,6 +567,29 @@ return true; } +static bool isKnownIntegral(const Value *V) { + if (isa(V)) + return true; + + if (const ConstantFP *CF = dyn_cast(V)) + return CF->getValueAPF().isInteger(); + + if (const ConstantDataVector *CDV = dyn_cast(V)) { + for (unsigned i = 0, e = CDV->getNumElements(); i != e; ++i) { + Constant *ConstElt = CDV->getElementAsConstant(i); + if (isa(ConstElt)) + continue; + const ConstantFP *CFP = dyn_cast(ConstElt); + if (!CFP || !CFP->getValue().isInteger()) + return false; + } + + return true; + } + + return false; +} + // This function returns false if no change; return true otherwise. bool AMDGPULibCalls::fold(CallInst *CI) { Function *Callee = CI->getCalledFunction(); @@ -990,25 +1013,8 @@ if (needcopysign && (FInfo.getId() == AMDGPULibFunc::EI_POW)) { // We cannot handle corner cases for a general pow() function, give up // unless y is a constant integral value. Then proceed as if it were pown. - if (getVecSize(FInfo) == 1) { - if (const ConstantFP *CF = dyn_cast(opr1)) { - double y = (getArgType(FInfo) == AMDGPULibFunc::F32) - ? (double)CF->getValueAPF().convertToFloat() - : CF->getValueAPF().convertToDouble(); - if (y != (double)(int64_t)y) - return false; - } else - return false; - } else { - if (const ConstantDataVector *CDV = dyn_cast(opr1)) { - for (int i=0; i < getVecSize(FInfo); ++i) { - double y = CDV->getElementAsAPFloat(i).convertToDouble(); - if (y != (double)(int64_t)y) - return false; - } - } else - return false; - } + if (!isKnownIntegral(opr1)) + return false; } Value *nval; Index: llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll +++ llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll @@ -1784,8 +1784,10 @@ define <2 x float> @test_pow_afn_v2f32_nnan_ninf__y_poison(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_pow_afn_v2f32_nnan_ninf__y_poison ; CHECK-SAME: (<2 x float> [[X:%.*]]) { -; CHECK-NEXT: [[POW:%.*]] = tail call nnan ninf afn <2 x float> @_Z3powDv2_fS_(<2 x float> [[X]], <2 x float> poison) -; CHECK-NEXT: ret <2 x float> [[POW]] +; CHECK-NEXT: [[__FABS:%.*]] = call nnan ninf afn <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]]) +; CHECK-NEXT: [[__LOG2:%.*]] = call nnan ninf afn <2 x float> @_Z4log2Dv2_f(<2 x float> [[__FABS]]) +; CHECK-NEXT: [[__EXP2:%.*]] = call nnan ninf afn <2 x float> @_Z4exp2Dv2_f(<2 x float> poison) +; CHECK-NEXT: ret <2 x float> poison ; %pow = tail call afn nnan ninf <2 x float> @_Z3powDv2_fS_(<2 x float> %x, <2 x float> poison) ret <2 x float> %pow