Skip to content

Commit f106f58

Browse files
committed
[InstCombine] Optimise x / sqrt(y / z) with fast-math pattern.
Replace the pattern with x * sqrt(z/y)
1 parent e50189b commit f106f58

File tree

2 files changed

+43
-15
lines changed

2 files changed

+43
-15
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,6 +1709,31 @@ static Instruction *foldFDivPowDivisor(BinaryOperator &I,
17091709
return BinaryOperator::CreateFMulFMF(Op0, Pow, &I);
17101710
}
17111711

1712+
/// Convert div to mul if we have an sqrt divisor iff sqrt's operand is a fdiv
1713+
/// instruction.
1714+
static Instruction *foldFDivSqrtDivisor(BinaryOperator &I,
1715+
InstCombiner::BuilderTy &Builder) {
1716+
// X / sqrt(Y / Z) --> X * sqrt(Z / Y)
1717+
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
1718+
auto *II = dyn_cast<IntrinsicInst>(Op1);
1719+
if (!II || II->getIntrinsicID() != Intrinsic::sqrt || !II->hasOneUse() ||
1720+
!I.hasAllowReassoc() || !I.hasAllowReciprocal())
1721+
return nullptr;
1722+
1723+
Value *Y, *Z;
1724+
auto *DivOp = dyn_cast<Instruction>(II->getOperand(0));
1725+
if (!DivOp || !DivOp->hasOneUse() || !DivOp->hasAllowReassoc() ||
1726+
!I.hasAllowReciprocal())
1727+
return nullptr;
1728+
if (match(DivOp, m_FDiv(m_Value(Y), m_Value(Z)))) {
1729+
Value *SwapDiv = Builder.CreateFDivFMF(Z, Y, DivOp);
1730+
Value *NewSqrt = Builder.CreateIntrinsic(II->getIntrinsicID(),
1731+
II->getType(), {SwapDiv}, II);
1732+
return BinaryOperator::CreateFMulFMF(Op0, NewSqrt, &I);
1733+
}
1734+
return nullptr;
1735+
}
1736+
17121737
Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
17131738
Module *M = I.getModule();
17141739

@@ -1816,6 +1841,9 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
18161841
if (Instruction *Mul = foldFDivPowDivisor(I, Builder))
18171842
return Mul;
18181843

1844+
if (Instruction *Mul = foldFDivSqrtDivisor(I, Builder))
1845+
return Mul;
1846+
18191847
// pow(X, Y) / X --> pow(X, Y-1)
18201848
if (I.hasAllowReassoc() &&
18211849
match(Op0, m_OneUse(m_Intrinsic<Intrinsic::pow>(m_Specific(Op1),

llvm/test/Transforms/InstCombine/fdiv-sqrt.ll

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ declare double @llvm.sqrt.f64(double)
66
define double @sqrt_div_fast(double %x, double %y, double %z) {
77
; CHECK-LABEL: @sqrt_div_fast(
88
; CHECK-NEXT: entry:
9-
; CHECK-NEXT: [[DIV:%.*]] = fdiv fast double [[Y:%.*]], [[Z:%.*]]
10-
; CHECK-NEXT: [[SQRT:%.*]] = call fast double @llvm.sqrt.f64(double [[DIV]])
11-
; CHECK-NEXT: [[DIV1:%.*]] = fdiv fast double [[X:%.*]], [[SQRT]]
9+
; CHECK-NEXT: [[TMP0:%.*]] = fdiv fast double [[Z:%.*]], [[Y:%.*]]
10+
; CHECK-NEXT: [[TMP1:%.*]] = call fast double @llvm.sqrt.f64(double [[TMP0]])
11+
; CHECK-NEXT: [[DIV1:%.*]] = fmul fast double [[TMP1]], [[X:%.*]]
1212
; CHECK-NEXT: ret double [[DIV1]]
1313
;
1414
entry:
@@ -36,9 +36,9 @@ entry:
3636
define double @sqrt_div_reassoc_arcp(double %x, double %y, double %z) {
3737
; CHECK-LABEL: @sqrt_div_reassoc_arcp(
3838
; CHECK-NEXT: entry:
39-
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc arcp double [[Y:%.*]], [[Z:%.*]]
40-
; CHECK-NEXT: [[SQRT:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[DIV]])
41-
; CHECK-NEXT: [[DIV1:%.*]] = fdiv reassoc arcp double [[X:%.*]], [[SQRT]]
39+
; CHECK-NEXT: [[TMP0:%.*]] = fdiv reassoc arcp double [[Z:%.*]], [[Y:%.*]]
40+
; CHECK-NEXT: [[TMP1:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[TMP0]])
41+
; CHECK-NEXT: [[DIV1:%.*]] = fmul reassoc arcp double [[TMP1]], [[X:%.*]]
4242
; CHECK-NEXT: ret double [[DIV1]]
4343
;
4444
entry:
@@ -66,9 +66,9 @@ entry:
6666
define double @sqrt_div_reassoc_missing2(double %x, double %y, double %z) {
6767
; CHECK-LABEL: @sqrt_div_reassoc_missing2(
6868
; CHECK-NEXT: entry:
69-
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc arcp double [[Y:%.*]], [[Z:%.*]]
70-
; CHECK-NEXT: [[SQRT:%.*]] = call arcp double @llvm.sqrt.f64(double [[DIV]])
71-
; CHECK-NEXT: [[DIV1:%.*]] = fdiv reassoc arcp double [[X:%.*]], [[SQRT]]
69+
; CHECK-NEXT: [[TMP0:%.*]] = fdiv reassoc arcp double [[Z:%.*]], [[Y:%.*]]
70+
; CHECK-NEXT: [[TMP1:%.*]] = call arcp double @llvm.sqrt.f64(double [[TMP0]])
71+
; CHECK-NEXT: [[DIV1:%.*]] = fmul reassoc arcp double [[TMP1]], [[X:%.*]]
7272
; CHECK-NEXT: ret double [[DIV1]]
7373
;
7474
entry:
@@ -96,9 +96,9 @@ entry:
9696
define double @sqrt_div_arcp_missing(double %x, double %y, double %z) {
9797
; CHECK-LABEL: @sqrt_div_arcp_missing(
9898
; CHECK-NEXT: entry:
99-
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[Y:%.*]], [[Z:%.*]]
100-
; CHECK-NEXT: [[SQRT:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[DIV]])
101-
; CHECK-NEXT: [[DIV1:%.*]] = fdiv reassoc arcp double [[X:%.*]], [[SQRT]]
99+
; CHECK-NEXT: [[TMP0:%.*]] = fdiv reassoc double [[Z:%.*]], [[Y:%.*]]
100+
; CHECK-NEXT: [[TMP1:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[TMP0]])
101+
; CHECK-NEXT: [[DIV1:%.*]] = fmul reassoc arcp double [[TMP1]], [[X:%.*]]
102102
; CHECK-NEXT: ret double [[DIV1]]
103103
;
104104
entry:
@@ -111,9 +111,9 @@ entry:
111111
define double @sqrt_div_arcp_missing2(double %x, double %y, double %z) {
112112
; CHECK-LABEL: @sqrt_div_arcp_missing2(
113113
; CHECK-NEXT: entry:
114-
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc arcp double [[Y:%.*]], [[Z:%.*]]
115-
; CHECK-NEXT: [[SQRT:%.*]] = call reassoc double @llvm.sqrt.f64(double [[DIV]])
116-
; CHECK-NEXT: [[DIV1:%.*]] = fdiv reassoc arcp double [[X:%.*]], [[SQRT]]
114+
; CHECK-NEXT: [[TMP0:%.*]] = fdiv reassoc arcp double [[Z:%.*]], [[Y:%.*]]
115+
; CHECK-NEXT: [[TMP1:%.*]] = call reassoc double @llvm.sqrt.f64(double [[TMP0]])
116+
; CHECK-NEXT: [[DIV1:%.*]] = fmul reassoc arcp double [[TMP1]], [[X:%.*]]
117117
; CHECK-NEXT: ret double [[DIV1]]
118118
;
119119
entry:

0 commit comments

Comments
 (0)