From 2ab4f529bb65cd8501ebdd700683d176773cba7c Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Mon, 15 Apr 2019 13:23:38 +0000 Subject: [PATCH] [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358404 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineMulDivRem.cpp | 8 +++++ test/Transforms/InstCombine/fast-math.ll | 4 +-- test/Transforms/InstCombine/fmul-pow.ll | 5 ++- test/Transforms/InstCombine/fmul.ll | 36 +++++++++---------- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 7edae55cb3e..a9e3e5f00f6 100644 --- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -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) // nnan disallows the possibility of returning a number if both operands are // negative (in that case, we should return NaN). diff --git a/test/Transforms/InstCombine/fast-math.ll b/test/Transforms/InstCombine/fast-math.ll index a3bfdc6ada2..b5173cc467c 100644 --- a/test/Transforms/InstCombine/fast-math.ll +++ b/test/Transforms/InstCombine/fast-math.ll @@ -599,8 +599,8 @@ define <2 x float> @fdiv2_vec(<2 x float> %x) { ; define float @fdiv3(float %x) { ; CHECK-LABEL: @fdiv3( -; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], 0x47EFFFFFE0000000 -; CHECK-NEXT: [[DIV1:%.*]] = fmul fast float [[DIV]], 0x3FDBD37A80000000 +; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[X:%.*]], 0x3FDBD37A80000000 +; CHECK-NEXT: [[DIV1:%.*]] = fdiv fast float [[TMP1]], 0x47EFFFFFE0000000 ; CHECK-NEXT: ret float [[DIV1]] ; %div = fdiv float %x, 0x47EFFFFFE0000000 diff --git a/test/Transforms/InstCombine/fmul-pow.ll b/test/Transforms/InstCombine/fmul-pow.ll index c85994cea71..7a020627269 100644 --- a/test/Transforms/InstCombine/fmul-pow.ll +++ b/test/Transforms/InstCombine/fmul-pow.ll @@ -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) { ; CHECK-LABEL: @pow_ab_a_reassoc_commute( -; CHECK-NEXT: [[TMP1:%.*]] = fdiv double 1.000000e+00, [[A:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A]], double [[B:%.*]]) -; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[TMP1]], [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]]) +; CHECK-NEXT: [[MUL:%.*]] = fdiv reassoc double [[TMP1]], [[A]] ; CHECK-NEXT: ret double [[MUL]] ; %1 = fdiv double 1.0, %a diff --git a/test/Transforms/InstCombine/fmul.ll b/test/Transforms/InstCombine/fmul.ll index be99d7f5b42..16d138539f9 100644 --- a/test/Transforms/InstCombine/fmul.ll +++ b/test/Transforms/InstCombine/fmul.ll @@ -383,10 +383,10 @@ define float @log2half(float %x, float %y) { define float @log2half_commute(float %x1, float %y) { ; 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: [[TMP1:%.*]] = fmul fast float [[LOG2]], [[X]] -; CHECK-NEXT: [[MUL:%.*]] = fsub fast float [[TMP1]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[LOG2]], [[X1:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fsub fast float [[TMP1]], [[X1]] +; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[TMP2]], 0x3FC24924A0000000 ; CHECK-NEXT: ret float [[MUL]] ; %x = fdiv float %x1, 7.0 ; thwart complexity-based canonicalization @@ -475,13 +475,13 @@ define float @fmul_constant_reassociation(float %x) { 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 define float @fdiv_constant_denominator_fmul_denorm(float %x) { ; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm( -; CHECK-NEXT: [[T1:%.*]] = fdiv float [[X:%.*]], 2.000000e+03 -; CHECK-NEXT: [[T3:%.*]] = fmul fast float [[T1]], 0x3810000000000000 +; CHECK-NEXT: [[T3:%.*]] = fmul fast float [[X:%.*]], 0x3760620000000000 ; CHECK-NEXT: ret float [[T3]] ; %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) { ; CHECK-LABEL: @fmul_fdivs_factor_common_denominator( -; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[X:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[DIV1]], [[DIV2]] +; CHECK-NEXT: [[TMP1:%.*]] = fmul fast double [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul fast double [[Z:%.*]], [[Z]] +; CHECK-NEXT: [[MUL:%.*]] = fdiv fast double [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret double [[MUL]] ; %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) { ; CHECK-LABEL: @fmul_fdivs_factor( -; CHECK-NEXT: [[DIV1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[DIV2:%.*]] = fdiv double [[Z:%.*]], [[W:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[DIV1]], [[DIV2]] +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[Z:%.*]], [[X:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fdiv reassoc double [[TMP1]], [[W:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = fdiv reassoc double [[TMP2]], [[Y:%.*]] ; CHECK-NEXT: ret double [[MUL]] ; %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) { ; CHECK-LABEL: @fmul_fdiv_factor( -; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[DIV]], [[Z:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = fdiv reassoc double [[TMP1]], [[Y:%.*]] ; CHECK-NEXT: ret double [[MUL]] ; %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) { ; CHECK-LABEL: @fmul_fdiv_factor_constant1( -; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[DIV]], 4.200000e+01 +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[X:%.*]], 4.200000e+01 +; CHECK-NEXT: [[MUL:%.*]] = fdiv reassoc double [[TMP1]], [[Y:%.*]] ; CHECK-NEXT: ret double [[MUL]] ; %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) { ; CHECK-LABEL: @fmul_fdiv_factor_constant2( -; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], -; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc <2 x float> [[DIV]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc <2 x float> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = fdiv reassoc <2 x float> [[TMP1]], ; CHECK-NEXT: ret <2 x float> [[MUL]] ; %div = fdiv <2 x float> %x, -- 2.50.1