diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index d1ca0dbab37bbc..0a2ec0993e00be 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1182,6 +1182,19 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { if (Power->equalsInt(2)) return BinaryOperator::CreateFMulFMF(II->getArgOperand(0), II->getArgOperand(0), II); + + if (!Power->getValue()[0]) { + Value *X; + // If power is even: + // powi(-x, p) -> powi(x, p) + // powi(fabs(x), p) -> powi(x, p) + // powi(copysign(x, y), p) -> powi(x, p) + if (match(II->getArgOperand(0), m_FNeg(m_Value(X))) || + match(II->getArgOperand(0), m_FAbs(m_Value(X))) || + match(II->getArgOperand(0), + m_Intrinsic(m_Value(X), m_Value()))) + return replaceOperand(*II, 0, X); + } } break; diff --git a/llvm/test/Transforms/InstCombine/powi.ll b/llvm/test/Transforms/InstCombine/powi.ll index 5fdb80211cbcb6..a8b492d28b9e24 100644 --- a/llvm/test/Transforms/InstCombine/powi.ll +++ b/llvm/test/Transforms/InstCombine/powi.ll @@ -8,8 +8,7 @@ declare double @llvm.copysign.f64(double, double) define double @powi_fneg_even_int(double %x) { ; CHECK-LABEL: @powi_fneg_even_int( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[FNEG:%.*]] = fneg double [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[FNEG]], i32 4) +; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4) ; CHECK-NEXT: ret double [[R]] ; entry: @@ -21,8 +20,7 @@ entry: define double @powi_fabs_even_int(double %x) { ; CHECK-LABEL: @powi_fabs_even_int( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[F:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]]) -; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[F]], i32 4) +; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4) ; CHECK-NEXT: ret double [[R]] ; entry: @@ -34,8 +32,7 @@ entry: define double @powi_copysign_even_int(double %x, double %y) { ; CHECK-LABEL: @powi_copysign_even_int( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CS:%.*]] = tail call double @llvm.copysign.f64(double [[X:%.*]], double [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[CS]], i32 4) +; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4) ; CHECK-NEXT: ret double [[R]] ; entry: