[InstCombine] Optimise x / sqrt(y / z) with fast-math pattern. (#76737)
Replace the pattern with x * sqrt(z/y) --------- Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
This commit is contained in:
parent
2884d04839
commit
bb5c3899d1
@ -1709,6 +1709,33 @@ static Instruction *foldFDivPowDivisor(BinaryOperator &I,
|
||||
return BinaryOperator::CreateFMulFMF(Op0, Pow, &I);
|
||||
}
|
||||
|
||||
/// Convert div to mul if we have an sqrt divisor iff sqrt's operand is a fdiv
|
||||
/// instruction.
|
||||
static Instruction *foldFDivSqrtDivisor(BinaryOperator &I,
|
||||
InstCombiner::BuilderTy &Builder) {
|
||||
// X / sqrt(Y / Z) --> X * sqrt(Z / Y)
|
||||
if (!I.hasAllowReassoc() || !I.hasAllowReciprocal())
|
||||
return nullptr;
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
auto *II = dyn_cast<IntrinsicInst>(Op1);
|
||||
if (!II || II->getIntrinsicID() != Intrinsic::sqrt || !II->hasOneUse() ||
|
||||
!II->hasAllowReassoc() || !II->hasAllowReciprocal())
|
||||
return nullptr;
|
||||
|
||||
Value *Y, *Z;
|
||||
auto *DivOp = dyn_cast<Instruction>(II->getOperand(0));
|
||||
if (!DivOp || !DivOp->hasAllowReassoc() || !I.hasAllowReciprocal() ||
|
||||
!DivOp->hasOneUse())
|
||||
return nullptr;
|
||||
if (match(DivOp, m_FDiv(m_Value(Y), m_Value(Z)))) {
|
||||
Value *SwapDiv = Builder.CreateFDivFMF(Z, Y, DivOp);
|
||||
Value *NewSqrt =
|
||||
Builder.CreateUnaryIntrinsic(II->getIntrinsicID(), SwapDiv, II);
|
||||
return BinaryOperator::CreateFMulFMF(Op0, NewSqrt, &I);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
|
||||
Module *M = I.getModule();
|
||||
|
||||
@ -1816,6 +1843,9 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
|
||||
if (Instruction *Mul = foldFDivPowDivisor(I, Builder))
|
||||
return Mul;
|
||||
|
||||
if (Instruction *Mul = foldFDivSqrtDivisor(I, Builder))
|
||||
return Mul;
|
||||
|
||||
// pow(X, Y) / X --> pow(X, Y-1)
|
||||
if (I.hasAllowReassoc() &&
|
||||
match(Op0, m_OneUse(m_Intrinsic<Intrinsic::pow>(m_Specific(Op1),
|
||||
|
||||
@ -6,9 +6,9 @@ declare double @llvm.sqrt.f64(double)
|
||||
define double @sqrt_div_fast(double %x, double %y, double %z) {
|
||||
; CHECK-LABEL: @sqrt_div_fast(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[DIV:%.*]] = fdiv fast double [[Y:%.*]], [[Z:%.*]]
|
||||
; CHECK-NEXT: [[SQRT:%.*]] = call fast double @llvm.sqrt.f64(double [[DIV]])
|
||||
; CHECK-NEXT: [[DIV1:%.*]] = fdiv fast double [[X:%.*]], [[SQRT]]
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = fdiv fast double [[Z:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call fast double @llvm.sqrt.f64(double [[TMP0]])
|
||||
; CHECK-NEXT: [[DIV1:%.*]] = fmul fast double [[TMP1]], [[X:%.*]]
|
||||
; CHECK-NEXT: ret double [[DIV1]]
|
||||
;
|
||||
entry:
|
||||
@ -36,9 +36,9 @@ entry:
|
||||
define double @sqrt_div_reassoc_arcp(double %x, double %y, double %z) {
|
||||
; CHECK-LABEL: @sqrt_div_reassoc_arcp(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc arcp double [[Y:%.*]], [[Z:%.*]]
|
||||
; CHECK-NEXT: [[SQRT:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[DIV]])
|
||||
; CHECK-NEXT: [[DIV1:%.*]] = fdiv reassoc arcp double [[X:%.*]], [[SQRT]]
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = fdiv reassoc arcp double [[Z:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[TMP0]])
|
||||
; CHECK-NEXT: [[DIV1:%.*]] = fmul reassoc arcp double [[TMP1]], [[X:%.*]]
|
||||
; CHECK-NEXT: ret double [[DIV1]]
|
||||
;
|
||||
entry:
|
||||
@ -96,9 +96,9 @@ entry:
|
||||
define double @sqrt_div_arcp_missing(double %x, double %y, double %z) {
|
||||
; CHECK-LABEL: @sqrt_div_arcp_missing(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[Y:%.*]], [[Z:%.*]]
|
||||
; CHECK-NEXT: [[SQRT:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[DIV]])
|
||||
; CHECK-NEXT: [[DIV1:%.*]] = fdiv reassoc arcp double [[X:%.*]], [[SQRT]]
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = fdiv reassoc double [[Z:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[TMP0]])
|
||||
; CHECK-NEXT: [[DIV1:%.*]] = fmul reassoc arcp double [[TMP1]], [[X:%.*]]
|
||||
; CHECK-NEXT: ret double [[DIV1]]
|
||||
;
|
||||
entry:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user