[InstCombine] canonicalize fdiv after fmul if reassociation is allowed

(X / Y) * Z --> (X * Z) / Y

This can allow other optimizations/reassociations as shown in the test diffs.

llvm-svn: 358404
This commit is contained in:
Sanjay Patel 2019-04-15 13:23:38 +00:00
parent 5db281cd4e
commit 5e13cd2e61
4 changed files with 30 additions and 23 deletions

View File

@ -430,6 +430,14 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
} }
} }
Value *Z;
if (match(&I, m_c_FMul(m_OneUse(m_FDiv(m_Value(X), m_Value(Y))),
m_Value(Z)))) {
// Sink division: (X / Y) * Z --> (X * Z) / Y
Value *NewFMul = Builder.CreateFMulFMF(X, Z, &I);
return BinaryOperator::CreateFDivFMF(NewFMul, Y, &I);
}
// sqrt(X) * sqrt(Y) -> sqrt(X * Y) // sqrt(X) * sqrt(Y) -> sqrt(X * Y)
// nnan disallows the possibility of returning a number if both operands are // nnan disallows the possibility of returning a number if both operands are
// negative (in that case, we should return NaN). // negative (in that case, we should return NaN).

View File

@ -599,8 +599,8 @@ define <2 x float> @fdiv2_vec(<2 x float> %x) {
; ;
define float @fdiv3(float %x) { define float @fdiv3(float %x) {
; CHECK-LABEL: @fdiv3( ; CHECK-LABEL: @fdiv3(
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], 0x47EFFFFFE0000000 ; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[X:%.*]], 0x3FDBD37A80000000
; CHECK-NEXT: [[DIV1:%.*]] = fmul fast float [[DIV]], 0x3FDBD37A80000000 ; CHECK-NEXT: [[DIV1:%.*]] = fdiv fast float [[TMP1]], 0x47EFFFFFE0000000
; CHECK-NEXT: ret float [[DIV1]] ; CHECK-NEXT: ret float [[DIV1]]
; ;
%div = fdiv float %x, 0x47EFFFFFE0000000 %div = fdiv float %x, 0x47EFFFFFE0000000

View File

@ -27,9 +27,8 @@ define double @pow_ab_a_reassoc(double %a, double %b) {
define double @pow_ab_a_reassoc_commute(double %a, double %b) { define double @pow_ab_a_reassoc_commute(double %a, double %b) {
; CHECK-LABEL: @pow_ab_a_reassoc_commute( ; CHECK-LABEL: @pow_ab_a_reassoc_commute(
; CHECK-NEXT: [[TMP1:%.*]] = fdiv double 1.000000e+00, [[A:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A]], double [[B:%.*]]) ; CHECK-NEXT: [[MUL:%.*]] = fdiv reassoc double [[TMP1]], [[A]]
; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret double [[MUL]] ; CHECK-NEXT: ret double [[MUL]]
; ;
%1 = fdiv double 1.0, %a %1 = fdiv double 1.0, %a

View File

@ -383,10 +383,10 @@ define float @log2half(float %x, float %y) {
define float @log2half_commute(float %x1, float %y) { define float @log2half_commute(float %x1, float %y) {
; CHECK-LABEL: @log2half_commute( ; CHECK-LABEL: @log2half_commute(
; CHECK-NEXT: [[X:%.*]] = fdiv float [[X1:%.*]], 7.000000e+00
; CHECK-NEXT: [[LOG2:%.*]] = call fast float @llvm.log2.f32(float [[Y:%.*]]) ; CHECK-NEXT: [[LOG2:%.*]] = call fast float @llvm.log2.f32(float [[Y:%.*]])
; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[LOG2]], [[X]] ; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[LOG2]], [[X1:%.*]]
; CHECK-NEXT: [[MUL:%.*]] = fsub fast float [[TMP1]], [[X]] ; CHECK-NEXT: [[TMP2:%.*]] = fsub fast float [[TMP1]], [[X1]]
; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[TMP2]], 0x3FC24924A0000000
; CHECK-NEXT: ret float [[MUL]] ; CHECK-NEXT: ret float [[MUL]]
; ;
%x = fdiv float %x1, 7.0 ; thwart complexity-based canonicalization %x = fdiv float %x1, 7.0 ; thwart complexity-based canonicalization
@ -475,13 +475,13 @@ define float @fmul_constant_reassociation(float %x) {
ret float %r ret float %r
} }
; Rule "X/C1 * C2 => X * (C2/C1) is not applicable if C2/C1 is abnormal ; Canonicalization "X/C1 * C2 => X * (C2/C1)" still applies if C2/C1 is denormal
; (otherwise, we should not have allowed the reassociation in the previous test).
; 0x3810000000000000 == FLT_MIN ; 0x3810000000000000 == FLT_MIN
define float @fdiv_constant_denominator_fmul_denorm(float %x) { define float @fdiv_constant_denominator_fmul_denorm(float %x) {
; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm( ; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm(
; CHECK-NEXT: [[T1:%.*]] = fdiv float [[X:%.*]], 2.000000e+03 ; CHECK-NEXT: [[T3:%.*]] = fmul fast float [[X:%.*]], 0x3760620000000000
; CHECK-NEXT: [[T3:%.*]] = fmul fast float [[T1]], 0x3810000000000000
; CHECK-NEXT: ret float [[T3]] ; CHECK-NEXT: ret float [[T3]]
; ;
%t1 = fdiv float %x, 2.0e+3 %t1 = fdiv float %x, 2.0e+3
@ -707,9 +707,9 @@ define double @fmul_fdiv_factor_squared(double %x, double %y) {
define double @fmul_fdivs_factor_common_denominator(double %x, double %y, double %z) { define double @fmul_fdivs_factor_common_denominator(double %x, double %y, double %z) {
; CHECK-LABEL: @fmul_fdivs_factor_common_denominator( ; CHECK-LABEL: @fmul_fdivs_factor_common_denominator(
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = fmul fast double [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[Y:%.*]], [[Z]] ; CHECK-NEXT: [[TMP2:%.*]] = fmul fast double [[Z:%.*]], [[Z]]
; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[DIV1]], [[DIV2]] ; CHECK-NEXT: [[MUL:%.*]] = fdiv fast double [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret double [[MUL]] ; CHECK-NEXT: ret double [[MUL]]
; ;
%div1 = fdiv double %x, %z %div1 = fdiv double %x, %z
@ -720,9 +720,9 @@ define double @fmul_fdivs_factor_common_denominator(double %x, double %y, double
define double @fmul_fdivs_factor(double %x, double %y, double %z, double %w) { define double @fmul_fdivs_factor(double %x, double %y, double %z, double %w) {
; CHECK-LABEL: @fmul_fdivs_factor( ; CHECK-LABEL: @fmul_fdivs_factor(
; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[Z:%.*]], [[X:%.*]]
; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[Z:%.*]], [[W:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = fdiv reassoc double [[TMP1]], [[W:%.*]]
; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[DIV1]], [[DIV2]] ; CHECK-NEXT: [[MUL:%.*]] = fdiv reassoc double [[TMP2]], [[Y:%.*]]
; CHECK-NEXT: ret double [[MUL]] ; CHECK-NEXT: ret double [[MUL]]
; ;
%div1 = fdiv double %x, %y %div1 = fdiv double %x, %y
@ -733,8 +733,8 @@ define double @fmul_fdivs_factor(double %x, double %y, double %z, double %w) {
define double @fmul_fdiv_factor(double %x, double %y, double %z) { define double @fmul_fdiv_factor(double %x, double %y, double %z) {
; CHECK-LABEL: @fmul_fdiv_factor( ; CHECK-LABEL: @fmul_fdiv_factor(
; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[X:%.*]], [[Z:%.*]]
; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[DIV]], [[Z:%.*]] ; CHECK-NEXT: [[MUL:%.*]] = fdiv reassoc double [[TMP1]], [[Y:%.*]]
; CHECK-NEXT: ret double [[MUL]] ; CHECK-NEXT: ret double [[MUL]]
; ;
%div = fdiv double %x, %y %div = fdiv double %x, %y
@ -744,8 +744,8 @@ define double @fmul_fdiv_factor(double %x, double %y, double %z) {
define double @fmul_fdiv_factor_constant1(double %x, double %y) { define double @fmul_fdiv_factor_constant1(double %x, double %y) {
; CHECK-LABEL: @fmul_fdiv_factor_constant1( ; CHECK-LABEL: @fmul_fdiv_factor_constant1(
; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[X:%.*]], 4.200000e+01
; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[DIV]], 4.200000e+01 ; CHECK-NEXT: [[MUL:%.*]] = fdiv reassoc double [[TMP1]], [[Y:%.*]]
; CHECK-NEXT: ret double [[MUL]] ; CHECK-NEXT: ret double [[MUL]]
; ;
%div = fdiv double %x, %y %div = fdiv double %x, %y
@ -755,8 +755,8 @@ define double @fmul_fdiv_factor_constant1(double %x, double %y) {
define <2 x float> @fmul_fdiv_factor_constant2(<2 x float> %x, <2 x float> %y) { define <2 x float> @fmul_fdiv_factor_constant2(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fmul_fdiv_factor_constant2( ; CHECK-LABEL: @fmul_fdiv_factor_constant2(
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float 1.200000e+01> ; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc <2 x float> [[DIV]], [[Y:%.*]] ; CHECK-NEXT: [[MUL:%.*]] = fdiv reassoc <2 x float> [[TMP1]], <float 4.200000e+01, float 1.200000e+01>
; CHECK-NEXT: ret <2 x float> [[MUL]] ; CHECK-NEXT: ret <2 x float> [[MUL]]
; ;
%div = fdiv <2 x float> %x, <float 42.0, float 12.0> %div = fdiv <2 x float> %x, <float 42.0, float 12.0>