forked from OSchip/llvm-project
[InstCombine] fix fmul reassociation to avoid creating an extra fdiv
This was supposed to be an NFC refactoring that will eventually allow eliminating the isFast() predicate, but there's a rare possibility that we would pessimize the code as shown in the test case because we failed to check 'hasOneUse()' properly. This version also removes an inefficiency of the old code; we would look for: (X * C) * C1 --> X * (C * C1) ...but that pattern is always handled by SimplifyAssociativeOrCommutative(). llvm-svn: 327404
This commit is contained in:
parent
476ed8f26e
commit
204edeca56
|
@ -557,14 +557,28 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
|
||||||
|
|
||||||
// Reassociate constant RHS with another constant to form constant expression.
|
// Reassociate constant RHS with another constant to form constant expression.
|
||||||
if (I.isFast() && match(Op1, m_Constant(C)) && C->isFiniteNonZeroFP()) {
|
if (I.isFast() && match(Op1, m_Constant(C)) && C->isFiniteNonZeroFP()) {
|
||||||
|
Constant *C1;
|
||||||
|
if (match(Op0, m_OneUse(m_FDiv(m_Constant(C1), m_Value(X))))) {
|
||||||
|
// (C1 / X) * C --> (C * C1) / X
|
||||||
|
Constant *CC1 = ConstantExpr::getFMul(C, C1);
|
||||||
|
if (CC1->isNormalFP())
|
||||||
|
return BinaryOperator::CreateFDivFMF(CC1, X, &I);
|
||||||
|
}
|
||||||
|
if (match(Op0, m_FDiv(m_Value(X), m_Constant(C1)))) {
|
||||||
|
// (X / C1) * C --> X * (C / C1)
|
||||||
|
Constant *CDivC1 = ConstantExpr::getFDiv(C, C1);
|
||||||
|
if (CDivC1->isNormalFP())
|
||||||
|
return BinaryOperator::CreateFMulFMF(X, CDivC1, &I);
|
||||||
|
|
||||||
|
// If the constant was a denormal, try reassociating differently.
|
||||||
|
// (X / C1) * C --> X / (C1 / C)
|
||||||
|
Constant *C1DivC = ConstantExpr::getFDiv(C1, C);
|
||||||
|
if (Op0->hasOneUse() && C1DivC->isNormalFP())
|
||||||
|
return BinaryOperator::CreateFDivFMF(X, C1DivC, &I);
|
||||||
|
}
|
||||||
|
|
||||||
// Let MDC denote an expression in one of these forms:
|
// Let MDC denote an expression in one of these forms:
|
||||||
// X * C, C/X, X/C, where C is a constant.
|
// X * C, C/X, X/C, where C is a constant.
|
||||||
//
|
|
||||||
// Try to simplify "MDC * Constant"
|
|
||||||
if (isFMulOrFDivWithConstant(Op0))
|
|
||||||
if (Value *V = foldFMulConst(cast<Instruction>(Op0), C, &I))
|
|
||||||
return replaceInstUsesWith(I, V);
|
|
||||||
|
|
||||||
// (MDC +/- C1) * C => (MDC * C) +/- (C1 * C)
|
// (MDC +/- C1) * C => (MDC * C) +/- (C1 * C)
|
||||||
Instruction *FAddSub = dyn_cast<Instruction>(Op0);
|
Instruction *FAddSub = dyn_cast<Instruction>(Op0);
|
||||||
if (FAddSub &&
|
if (FAddSub &&
|
||||||
|
|
|
@ -336,8 +336,8 @@ define float @log2half_commute(float %x1, float %y) {
|
||||||
|
|
||||||
define float @fdiv_constant_numerator_fmul(float %x) {
|
define float @fdiv_constant_numerator_fmul(float %x) {
|
||||||
; CHECK-LABEL: @fdiv_constant_numerator_fmul(
|
; CHECK-LABEL: @fdiv_constant_numerator_fmul(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = fdiv fast float 1.200000e+07, [[X:%.*]]
|
; CHECK-NEXT: [[T3:%.*]] = fdiv fast float 1.200000e+07, [[X:%.*]]
|
||||||
; CHECK-NEXT: ret float [[TMP1]]
|
; CHECK-NEXT: ret float [[T3]]
|
||||||
;
|
;
|
||||||
%t1 = fdiv float 2.0e+3, %x
|
%t1 = fdiv float 2.0e+3, %x
|
||||||
%t3 = fmul fast float %t1, 6.0e+3
|
%t3 = fmul fast float %t1, 6.0e+3
|
||||||
|
@ -365,8 +365,8 @@ define float @fdiv_constant_numerator_fmul_extra_use(float %x) {
|
||||||
|
|
||||||
define float @fdiv_constant_denominator_fmul(float %x) {
|
define float @fdiv_constant_denominator_fmul(float %x) {
|
||||||
; CHECK-LABEL: @fdiv_constant_denominator_fmul(
|
; CHECK-LABEL: @fdiv_constant_denominator_fmul(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[X:%.*]], 3.000000e+00
|
; CHECK-NEXT: [[T3:%.*]] = fmul fast float [[X:%.*]], 3.000000e+00
|
||||||
; CHECK-NEXT: ret float [[TMP1]]
|
; CHECK-NEXT: ret float [[T3]]
|
||||||
;
|
;
|
||||||
%t1 = fdiv float %x, 2.0e+3
|
%t1 = fdiv float %x, 2.0e+3
|
||||||
%t3 = fmul fast float %t1, 6.0e+3
|
%t3 = fmul fast float %t1, 6.0e+3
|
||||||
|
@ -375,8 +375,8 @@ define float @fdiv_constant_denominator_fmul(float %x) {
|
||||||
|
|
||||||
define <4 x float> @fdiv_constant_denominator_fmul_vec(<4 x float> %x) {
|
define <4 x float> @fdiv_constant_denominator_fmul_vec(<4 x float> %x) {
|
||||||
; CHECK-LABEL: @fdiv_constant_denominator_fmul_vec(
|
; CHECK-LABEL: @fdiv_constant_denominator_fmul_vec(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = fmul fast <4 x float> [[X:%.*]], <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00, float 1.000000e+00>
|
; CHECK-NEXT: [[T3:%.*]] = fmul fast <4 x float> [[X:%.*]], <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00, float 1.000000e+00>
|
||||||
; CHECK-NEXT: ret <4 x float> [[TMP1]]
|
; CHECK-NEXT: ret <4 x float> [[T3]]
|
||||||
;
|
;
|
||||||
%t1 = fdiv <4 x float> %x, <float 2.0e+3, float 3.0e+3, float 2.0e+3, float 1.0e+3>
|
%t1 = fdiv <4 x float> %x, <float 2.0e+3, float 3.0e+3, float 2.0e+3, float 1.0e+3>
|
||||||
%t3 = fmul fast <4 x float> %t1, <float 6.0e+3, float 6.0e+3, float 2.0e+3, float 1.0e+3>
|
%t3 = fmul fast <4 x float> %t1, <float 6.0e+3, float 6.0e+3, float 2.0e+3, float 1.0e+3>
|
||||||
|
@ -387,8 +387,8 @@ define <4 x float> @fdiv_constant_denominator_fmul_vec(<4 x float> %x) {
|
||||||
|
|
||||||
define <4 x float> @fdiv_constant_denominator_fmul_vec_constexpr(<4 x float> %x) {
|
define <4 x float> @fdiv_constant_denominator_fmul_vec_constexpr(<4 x float> %x) {
|
||||||
; CHECK-LABEL: @fdiv_constant_denominator_fmul_vec_constexpr(
|
; CHECK-LABEL: @fdiv_constant_denominator_fmul_vec_constexpr(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = fmul fast <4 x float> [[X:%.*]], <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00, float 1.000000e+00>
|
; CHECK-NEXT: [[T3:%.*]] = fmul fast <4 x float> [[X:%.*]], <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00, float 1.000000e+00>
|
||||||
; CHECK-NEXT: ret <4 x float> [[TMP1]]
|
; CHECK-NEXT: ret <4 x float> [[T3]]
|
||||||
;
|
;
|
||||||
%constExprMul = bitcast i128 trunc (i160 bitcast (<5 x float> <float 6.0e+3, float 6.0e+3, float 2.0e+3, float 1.0e+3, float undef> to i160) to i128) to <4 x float>
|
%constExprMul = bitcast i128 trunc (i160 bitcast (<5 x float> <float 6.0e+3, float 6.0e+3, float 2.0e+3, float 1.0e+3, float undef> to i160) to i128) to <4 x float>
|
||||||
%t1 = fdiv <4 x float> %x, <float 2.0e+3, float 3.0e+3, float 2.0e+3, float 1.0e+3>
|
%t1 = fdiv <4 x float> %x, <float 2.0e+3, float 3.0e+3, float 2.0e+3, float 1.0e+3>
|
||||||
|
@ -416,21 +416,21 @@ define float @fdiv_constant_denominator_fmul_denorm(float %x) {
|
||||||
|
|
||||||
define float @fdiv_constant_denominator_fmul_denorm_try_harder(float %x) {
|
define float @fdiv_constant_denominator_fmul_denorm_try_harder(float %x) {
|
||||||
; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm_try_harder(
|
; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm_try_harder(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = fdiv fast float [[X:%.*]], 0x47E8000000000000
|
; CHECK-NEXT: [[T3:%.*]] = fdiv fast float [[X:%.*]], 0x47E8000000000000
|
||||||
; CHECK-NEXT: ret float [[TMP1]]
|
; CHECK-NEXT: ret float [[T3]]
|
||||||
;
|
;
|
||||||
%t1 = fdiv float %x, 3.0
|
%t1 = fdiv float %x, 3.0
|
||||||
%t3 = fmul fast float %t1, 0x3810000000000000
|
%t3 = fmul fast float %t1, 0x3810000000000000
|
||||||
ret float %t3
|
ret float %t3
|
||||||
}
|
}
|
||||||
|
|
||||||
; FIXME: We have 2 divisions instead of the 1 we started with.
|
; Negative test: we should not have 2 divisions instead of the 1 we started with.
|
||||||
|
|
||||||
define float @fdiv_constant_denominator_fmul_denorm_try_harder_extra_use(float %x) {
|
define float @fdiv_constant_denominator_fmul_denorm_try_harder_extra_use(float %x) {
|
||||||
; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm_try_harder_extra_use(
|
; CHECK-LABEL: @fdiv_constant_denominator_fmul_denorm_try_harder_extra_use(
|
||||||
; CHECK-NEXT: [[T1:%.*]] = fdiv float [[X:%.*]], 3.000000e+00
|
; CHECK-NEXT: [[T1:%.*]] = fdiv float [[X:%.*]], 3.000000e+00
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = fdiv fast float [[X]], 0x47E8000000000000
|
; CHECK-NEXT: [[T3:%.*]] = fmul fast float [[T1]], 0x3810000000000000
|
||||||
; CHECK-NEXT: [[R:%.*]] = fadd float [[T1]], [[TMP1]]
|
; CHECK-NEXT: [[R:%.*]] = fadd float [[T1]], [[T3]]
|
||||||
; CHECK-NEXT: ret float [[R]]
|
; CHECK-NEXT: ret float [[R]]
|
||||||
;
|
;
|
||||||
%t1 = fdiv float %x, 3.0e+0
|
%t1 = fdiv float %x, 3.0e+0
|
||||||
|
|
Loading…
Reference in New Issue