Fast-math fold: x / (y * sqrt(z)) -> x * (rsqrt(z) / y)
The motivation is to recognize code such as this from /llvm/projects/test-suite/SingleSource/Benchmarks/BenchmarkGame/n-body.c:
float distance = sqrt(dx * dx + dy * dy + dz * dz);
float mag = dt / (distance * distance * distance);
Without this patch, we don't match the sqrt as a reciprocal sqrt, so for PPC the new testcase in this patch produces:
addis 3, 2, .LCPI4_2@toc@ha
lfs 4, .LCPI4_2@toc@l(3)
addis 3, 2, .LCPI4_1@toc@ha
lfs 0, .LCPI4_1@toc@l(3)
fcmpu 0, 1, 4
beq 0, .LBB4_2
# BB#1:
frsqrtes 4, 1
addis 3, 2, .LCPI4_0@toc@ha
lfs 5, .LCPI4_0@toc@l(3)
fnmsubs 13, 1, 5, 1
fmuls 6, 4, 4
fmadds 1, 13, 6, 5
fmuls 1, 4, 1
fres 4, 1 <--- reciprocal of reciprocal square root
fnmsubs 1, 1, 4, 0
fmadds 4, 4, 1, 4
.LBB4_2:
fmuls 1, 4, 2
fres 2, 1
fnmsubs 0, 1, 2, 0
fmadds 0, 2, 0, 2
fmuls 1, 3, 0
blr
After the patch, this simplifies to:
frsqrtes 0, 1
addis 3, 2, .LCPI4_1@toc@ha
fres 5, 2
lfs 4, .LCPI4_1@toc@l(3)
addis 3, 2, .LCPI4_0@toc@ha
lfs 7, .LCPI4_0@toc@l(3)
fnmsubs 13, 1, 4, 1
fmuls 6, 0, 0
fnmsubs 2, 2, 5, 7
fmadds 1, 13, 6, 4
fmadds 2, 5, 2, 5
fmuls 0, 0, 1
fmuls 0, 0, 2
fmuls 1, 3, 0
blr
Differential Revision: http://reviews.llvm.org/D5628
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219139 91177308-0d34-0410-b5e6-96231b3b80d8