[llvm] r339519 - [InstCombine] fix/enhance fadd/fsub factorization

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 12 08:48:26 PDT 2018


Author: spatel
Date: Sun Aug 12 08:48:26 2018
New Revision: 339519

URL: http://llvm.org/viewvc/llvm-project?rev=339519&view=rev
Log:
[InstCombine] fix/enhance fadd/fsub factorization
  (X * Z) + (Y * Z) --> (X + Y) * Z
  (X * Z) - (Y * Z) --> (X - Y) * Z
  (X / Z) + (Y / Z) --> (X + Y) / Z
  (X / Z) - (Y / Z) --> (X - Y) / Z

The existing code that implemented these folds failed to 
optimize vectors, and it transformed code with multiple 
uses when it should not have.

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
    llvm/trunk/test/Transforms/InstCombine/fadd-fsub-factor.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp?rev=339519&r1=339518&r2=339519&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp Sun Aug 12 08:48:26 2018
@@ -186,8 +186,6 @@ namespace {
 
     Value *simplifyFAdd(AddendVect& V, unsigned InstrQuota);
 
-    Value *performFactorization(Instruction *I);
-
     /// Convert given addend to a Value
     Value *createAddendVal(const FAddend &A, bool& NeedNeg);
 
@@ -427,89 +425,6 @@ unsigned FAddend::drillAddendDownOneStep
   return BreakNum;
 }
 
-// Try to perform following optimization on the input instruction I. Return the
-// simplified expression if was successful; otherwise, return 0.
-//
-//   Instruction "I" is                Simplified into
-// -------------------------------------------------------
-//   (x * y) +/- (x * z)               x * (y +/- z)
-//   (y / x) +/- (z / x)               (y +/- z) / x
-Value *FAddCombine::performFactorization(Instruction *I) {
-  assert((I->getOpcode() == Instruction::FAdd ||
-          I->getOpcode() == Instruction::FSub) && "Expect add/sub");
-
-  Instruction *I0 = dyn_cast<Instruction>(I->getOperand(0));
-  Instruction *I1 = dyn_cast<Instruction>(I->getOperand(1));
-
-  if (!I0 || !I1 || I0->getOpcode() != I1->getOpcode())
-    return nullptr;
-
-  bool isMpy = false;
-  if (I0->getOpcode() == Instruction::FMul)
-    isMpy = true;
-  else if (I0->getOpcode() != Instruction::FDiv)
-    return nullptr;
-
-  Value *Opnd0_0 = I0->getOperand(0);
-  Value *Opnd0_1 = I0->getOperand(1);
-  Value *Opnd1_0 = I1->getOperand(0);
-  Value *Opnd1_1 = I1->getOperand(1);
-
-  //  Input Instr I       Factor   AddSub0  AddSub1
-  //  ----------------------------------------------
-  // (x*y) +/- (x*z)        x        y         z
-  // (y/x) +/- (z/x)        x        y         z
-  Value *Factor = nullptr;
-  Value *AddSub0 = nullptr, *AddSub1 = nullptr;
-
-  if (isMpy) {
-    if (Opnd0_0 == Opnd1_0 || Opnd0_0 == Opnd1_1)
-      Factor = Opnd0_0;
-    else if (Opnd0_1 == Opnd1_0 || Opnd0_1 == Opnd1_1)
-      Factor = Opnd0_1;
-
-    if (Factor) {
-      AddSub0 = (Factor == Opnd0_0) ? Opnd0_1 : Opnd0_0;
-      AddSub1 = (Factor == Opnd1_0) ? Opnd1_1 : Opnd1_0;
-    }
-  } else if (Opnd0_1 == Opnd1_1) {
-    Factor = Opnd0_1;
-    AddSub0 = Opnd0_0;
-    AddSub1 = Opnd1_0;
-  }
-
-  if (!Factor)
-    return nullptr;
-
-  FastMathFlags Flags;
-  Flags.setFast();
-  if (I0) Flags &= I->getFastMathFlags();
-  if (I1) Flags &= I->getFastMathFlags();
-
-  // Create expression "NewAddSub = AddSub0 +/- AddsSub1"
-  Value *NewAddSub = (I->getOpcode() == Instruction::FAdd) ?
-                      createFAdd(AddSub0, AddSub1) :
-                      createFSub(AddSub0, AddSub1);
-  if (ConstantFP *CFP = dyn_cast<ConstantFP>(NewAddSub)) {
-    const APFloat &F = CFP->getValueAPF();
-    if (!F.isNormal())
-      return nullptr;
-  } else if (Instruction *II = dyn_cast<Instruction>(NewAddSub))
-    II->setFastMathFlags(Flags);
-
-  if (isMpy) {
-    Value *RI = createFMul(Factor, NewAddSub);
-    if (Instruction *II = dyn_cast<Instruction>(RI))
-      II->setFastMathFlags(Flags);
-    return RI;
-  }
-
-  Value *RI = createFDiv(NewAddSub, Factor);
-  if (Instruction *II = dyn_cast<Instruction>(RI))
-    II->setFastMathFlags(Flags);
-  return RI;
-}
-
 Value *FAddCombine::simplify(Instruction *I) {
   assert(I->hasAllowReassoc() && I->hasNoSignedZeros() &&
          "Expected 'reassoc'+'nsz' instruction");
@@ -594,8 +509,7 @@ Value *FAddCombine::simplify(Instruction
       return R;
   }
 
-  // step 6: Try factorization as the last resort,
-  return performFactorization(I);
+  return nullptr;
 }
 
 Value *FAddCombine::simplifyFAdd(AddendVect& Addends, unsigned InstrQuota) {
@@ -1391,6 +1305,45 @@ Instruction *InstCombiner::visitAdd(Bina
   return Changed ? &I : nullptr;
 }
 
+/// Factor a common operand out of fadd/fsub of fmul/fdiv.
+static Instruction *factorizeFAddFSub(BinaryOperator &I,
+                                      InstCombiner::BuilderTy &Builder) {
+  assert((I.getOpcode() == Instruction::FAdd ||
+          I.getOpcode() == Instruction::FSub) && "Expecting fadd/fsub");
+  assert(I.hasAllowReassoc() && I.hasNoSignedZeros() &&
+         "FP factorization requires FMF");
+  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+  Value *X, *Y, *Z;
+  bool IsFMul;
+  if ((match(Op0, m_OneUse(m_FMul(m_Value(X), m_Value(Z)))) &&
+       match(Op1, m_OneUse(m_c_FMul(m_Value(Y), m_Specific(Z))))) ||
+      (match(Op0, m_OneUse(m_FMul(m_Value(Z), m_Value(X)))) &&
+       match(Op1, m_OneUse(m_c_FMul(m_Value(Y), m_Specific(Z))))))
+    IsFMul = true;
+  else if (match(Op0, m_OneUse(m_FDiv(m_Value(X), m_Value(Z)))) &&
+           match(Op1, m_OneUse(m_FDiv(m_Value(Y), m_Specific(Z)))))
+    IsFMul = false;
+  else
+    return nullptr;
+
+  // (X * Z) + (Y * Z) --> (X + Y) * Z
+  // (X * Z) - (Y * Z) --> (X - Y) * Z
+  // (X / Z) + (Y / Z) --> (X + Y) / Z
+  // (X / Z) - (Y / Z) --> (X - Y) / Z
+  bool IsFAdd = I.getOpcode() == Instruction::FAdd;
+  Value *XY = IsFAdd ? Builder.CreateFAddFMF(X, Y, &I)
+                     : Builder.CreateFSubFMF(X, Y, &I);
+
+  // Bail out if we just created a denormal constant.
+  // TODO: This is copied from a previous implementation. Is it necessary?
+  const APFloat *C;
+  if (match(XY, m_APFloat(C)) && !C->isNormal())
+    return nullptr;
+
+  return IsFMul ? BinaryOperator::CreateFMulFMF(XY, Z, &I)
+                : BinaryOperator::CreateFDivFMF(XY, Z, &I);
+}
+
 Instruction *InstCombiner::visitFAdd(BinaryOperator &I) {
   if (Value *V = SimplifyFAddInst(I.getOperand(0), I.getOperand(1),
                                   I.getFastMathFlags(),
@@ -1478,6 +1431,8 @@ Instruction *InstCombiner::visitFAdd(Bin
     return replaceInstUsesWith(I, V);
 
   if (I.hasAllowReassoc() && I.hasNoSignedZeros()) {
+    if (Instruction *F = factorizeFAddFSub(I, Builder))
+      return F;
     if (Value *V = FAddCombine(Builder).simplify(&I))
       return replaceInstUsesWith(I, V);
   }
@@ -1925,6 +1880,9 @@ Instruction *InstCombiner::visitFSub(Bin
       return BinaryOperator::CreateFMulFMF(Op0, OneSubC, &I);
     }
 
+    if (Instruction *F = factorizeFAddFSub(I, Builder))
+      return F;
+
     // TODO: This performs reassociative folds for FP ops. Some fraction of the
     // functionality has been subsumed by simple pattern matching here and in
     // InstSimplify. We should let a dedicated reassociation pass handle more

Modified: llvm/trunk/test/Transforms/InstCombine/fadd-fsub-factor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fadd-fsub-factor.ll?rev=339519&r1=339518&r2=339519&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fadd-fsub-factor.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fadd-fsub-factor.ll Sun Aug 12 08:48:26 2018
@@ -16,8 +16,8 @@
 define float @fmul_fadd(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fmul_fadd(
 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]]
-; CHECK-NEXT:    ret float [[TMP2]]
+; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fmul float %x, %z
   %t2 = fmul float %y, %z
@@ -25,14 +25,12 @@ define float @fmul_fadd(float %x, float
   ret float %r
 }
 
-; FIXME:
 ; Verify vector types and commuted operands.
 
 define <2 x float> @fmul_fadd_commute1_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
 ; CHECK-LABEL: @fmul_fadd_commute1_vec(
-; CHECK-NEXT:    [[T1:%.*]] = fmul <2 x float> [[Z:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[T2:%.*]] = fmul <2 x float> [[Z]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz <2 x float> [[T1]], [[T2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz <2 x float> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz <2 x float> [[TMP1]], [[Z:%.*]]
 ; CHECK-NEXT:    ret <2 x float> [[R]]
 ;
   %t1 = fmul <2 x float> %z, %x
@@ -41,14 +39,12 @@ define <2 x float> @fmul_fadd_commute1_v
   ret <2 x float> %r
 }
 
-; FIXME:
 ; Verify vector types, commuted operands, FMF propagation.
 
 define <2 x float> @fmul_fadd_commute2_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
 ; CHECK-LABEL: @fmul_fadd_commute2_vec(
-; CHECK-NEXT:    [[T1:%.*]] = fmul fast <2 x float> [[X:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[T2:%.*]] = fmul nnan <2 x float> [[Z]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = fadd reassoc ninf nsz <2 x float> [[T1]], [[T2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc ninf nsz <2 x float> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fmul reassoc ninf nsz <2 x float> [[TMP1]], [[Z:%.*]]
 ; CHECK-NEXT:    ret <2 x float> [[R]]
 ;
   %t1 = fmul fast <2 x float> %x, %z
@@ -62,8 +58,8 @@ define <2 x float> @fmul_fadd_commute2_v
 define double @fmul_fadd_commute3(double %x, double %y, double %z) {
 ; CHECK-LABEL: @fmul_fadd_commute3(
 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nnan nsz double [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc nnan nsz double [[TMP1]], [[Z:%.*]]
-; CHECK-NEXT:    ret double [[TMP2]]
+; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nnan nsz double [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    ret double [[R]]
 ;
   %t1 = fmul double %z, %x
   %t2 = fmul fast double %y, %z
@@ -88,16 +84,15 @@ define float @fmul_fadd_not_enough_FMF(f
 
 declare void @use(float)
 
-; FIXME:
 ; Negative test - extra uses should disable the fold.
 
 define float @fmul_fadd_uses1(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fmul_fadd_uses1(
 ; CHECK-NEXT:    [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[X]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]]
+; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[T1]], [[T2]]
 ; CHECK-NEXT:    call void @use(float [[T1]])
-; CHECK-NEXT:    ret float [[TMP2]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fmul float %z, %x
   %t2 = fmul float %y, %z
@@ -106,16 +101,15 @@ define float @fmul_fadd_uses1(float %x,
   ret float %r
 }
 
-; FIXME:
 ; Negative test - extra uses should disable the fold.
 
 define float @fmul_fadd_uses2(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fmul_fadd_uses2(
-; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Z:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[X:%.*]], [[Y]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]]
+; CHECK-NEXT:    [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Z]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[T1]], [[T2]]
 ; CHECK-NEXT:    call void @use(float [[T2]])
-; CHECK-NEXT:    ret float [[TMP2]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fmul float %z, %x
   %t2 = fmul float %z, %y
@@ -124,18 +118,16 @@ define float @fmul_fadd_uses2(float %x,
   ret float %r
 }
 
-; FIXME:
 ; Negative test - extra uses should disable the fold.
 
 define float @fmul_fadd_uses3(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fmul_fadd_uses3(
 ; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]]
 ; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Z]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz float [[X]], [[Y]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]]
+; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[T1]], [[T2]]
 ; CHECK-NEXT:    call void @use(float [[T1]])
 ; CHECK-NEXT:    call void @use(float [[T2]])
-; CHECK-NEXT:    ret float [[TMP2]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fmul float %x, %z
   %t2 = fmul float %z, %y
@@ -150,8 +142,8 @@ define float @fmul_fadd_uses3(float %x,
 define half @fmul_fsub(half %x, half %y, half %z) {
 ; CHECK-LABEL: @fmul_fsub(
 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz half [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc nsz half [[TMP1]], [[Z:%.*]]
-; CHECK-NEXT:    ret half [[TMP2]]
+; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz half [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    ret half [[R]]
 ;
   %t1 = fmul half %x, %z
   %t2 = fmul half %y, %z
@@ -159,14 +151,12 @@ define half @fmul_fsub(half %x, half %y,
   ret half %r
 }
 
-; FIXME:
 ; Verify vector types and commuted operands.
 
 define <2 x float> @fmul_fsub_commute1_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
 ; CHECK-LABEL: @fmul_fsub_commute1_vec(
-; CHECK-NEXT:    [[T1:%.*]] = fmul <2 x float> [[Z:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[T2:%.*]] = fmul <2 x float> [[Y:%.*]], [[Z]]
-; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz <2 x float> [[T1]], [[T2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz <2 x float> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz <2 x float> [[TMP1]], [[Z:%.*]]
 ; CHECK-NEXT:    ret <2 x float> [[R]]
 ;
   %t1 = fmul <2 x float> %z, %x
@@ -175,14 +165,12 @@ define <2 x float> @fmul_fsub_commute1_v
   ret <2 x float> %r
 }
 
-; FIXME:
 ; Verify vector types, commuted operands, FMF propagation.
 
 define <2 x float> @fmul_fsub_commute2_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
 ; CHECK-LABEL: @fmul_fsub_commute2_vec(
-; CHECK-NEXT:    [[T1:%.*]] = fmul fast <2 x float> [[X:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[T2:%.*]] = fmul nnan <2 x float> [[Z]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = fsub reassoc ninf nsz <2 x float> [[T1]], [[T2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc ninf nsz <2 x float> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fmul reassoc ninf nsz <2 x float> [[TMP1]], [[Z:%.*]]
 ; CHECK-NEXT:    ret <2 x float> [[R]]
 ;
   %t1 = fmul fast <2 x float> %x, %z
@@ -196,8 +184,8 @@ define <2 x float> @fmul_fsub_commute2_v
 define double @fmul_fsub_commute3(double %x, double %y, double %z) {
 ; CHECK-LABEL: @fmul_fsub_commute3(
 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nnan nsz double [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc nnan nsz double [[TMP1]], [[Z:%.*]]
-; CHECK-NEXT:    ret double [[TMP2]]
+; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nnan nsz double [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    ret double [[R]]
 ;
   %t1 = fmul double %z, %x
   %t2 = fmul fast double %z, %y
@@ -220,16 +208,15 @@ define float @fmul_fsub_not_enough_FMF(f
   ret float %r
 }
 
-; FIXME:
 ; Negative test - extra uses should disable the fold.
 
 define float @fmul_fsub_uses1(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fmul_fsub_uses1(
 ; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz float [[X]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]]
+; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[T1]], [[T2]]
 ; CHECK-NEXT:    call void @use(float [[T1]])
-; CHECK-NEXT:    ret float [[TMP2]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fmul float %x, %z
   %t2 = fmul float %y, %z
@@ -238,16 +225,15 @@ define float @fmul_fsub_uses1(float %x,
   ret float %r
 }
 
-; FIXME:
 ; Negative test - extra uses should disable the fold.
 
 define float @fmul_fsub_uses2(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fmul_fsub_uses2(
-; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Z:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]]
+; CHECK-NEXT:    [[T1:%.*]] = fmul float [[Z:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Z]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[T1]], [[T2]]
 ; CHECK-NEXT:    call void @use(float [[T2]])
-; CHECK-NEXT:    ret float [[TMP2]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fmul float %z, %x
   %t2 = fmul float %z, %y
@@ -256,18 +242,16 @@ define float @fmul_fsub_uses2(float %x,
   ret float %r
 }
 
-; FIXME:
 ; Negative test - extra uses should disable the fold.
 
 define float @fmul_fsub_uses3(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fmul_fsub_uses3(
 ; CHECK-NEXT:    [[T1:%.*]] = fmul float [[X:%.*]], [[Z:%.*]]
 ; CHECK-NEXT:    [[T2:%.*]] = fmul float [[Y:%.*]], [[Z]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz float [[X]], [[Y]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z]]
+; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[T1]], [[T2]]
 ; CHECK-NEXT:    call void @use(float [[T1]])
 ; CHECK-NEXT:    call void @use(float [[T2]])
-; CHECK-NEXT:    ret float [[TMP2]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fmul float %x, %z
   %t2 = fmul float %y, %z
@@ -282,8 +266,8 @@ define float @fmul_fsub_uses3(float %x,
 define double @fdiv_fadd(double %x, double %y, double %z) {
 ; CHECK-LABEL: @fdiv_fadd(
 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz double [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fdiv reassoc nsz double [[TMP1]], [[Z:%.*]]
-; CHECK-NEXT:    ret double [[TMP2]]
+; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc nsz double [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    ret double [[R]]
 ;
   %t1 = fdiv double %x, %z
   %t2 = fdiv double %y, %z
@@ -294,8 +278,8 @@ define double @fdiv_fadd(double %x, doub
 define float @fdiv_fsub(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fdiv_fsub(
 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fdiv reassoc nsz float [[TMP1]], [[Z:%.*]]
-; CHECK-NEXT:    ret float [[TMP2]]
+; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc nsz float [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fdiv fast float %x, %z
   %t2 = fdiv nnan float %y, %z
@@ -303,14 +287,12 @@ define float @fdiv_fsub(float %x, float
   ret float %r
 }
 
-; FIXME:
 ; Verify vector types.
 
 define <2 x double> @fdiv_fadd_vec(<2 x double> %x, <2 x double> %y, <2 x double> %z) {
 ; CHECK-LABEL: @fdiv_fadd_vec(
-; CHECK-NEXT:    [[T1:%.*]] = fdiv fast <2 x double> [[X:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[T2:%.*]] = fdiv <2 x double> [[Y:%.*]], [[Z]]
-; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz <2 x double> [[T1]], [[T2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc nsz <2 x double> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc nsz <2 x double> [[TMP1]], [[Z:%.*]]
 ; CHECK-NEXT:    ret <2 x double> [[R]]
 ;
   %t1 = fdiv fast <2 x double> %x, %z
@@ -319,14 +301,12 @@ define <2 x double> @fdiv_fadd_vec(<2 x
   ret <2 x double> %r
 }
 
-; FIXME:
 ; Verify vector types.
 
 define <2 x float> @fdiv_fsub_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
 ; CHECK-LABEL: @fdiv_fsub_vec(
-; CHECK-NEXT:    [[T1:%.*]] = fdiv <2 x float> [[X:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[T2:%.*]] = fdiv nnan <2 x float> [[Y:%.*]], [[Z]]
-; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz <2 x float> [[T1]], [[T2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fsub reassoc nsz <2 x float> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc nsz <2 x float> [[TMP1]], [[Z:%.*]]
 ; CHECK-NEXT:    ret <2 x float> [[R]]
 ;
   %t1 = fdiv <2 x float> %x, %z
@@ -395,16 +375,15 @@ define float @fdiv_fsub_not_enough_FMF(f
   ret float %t3
 }
 
-; FIXME:
 ; Negative test - extra uses should disable the fold.
 
 define float @fdiv_fadd_uses1(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fdiv_fadd_uses1(
 ; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fadd fast float [[X]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fdiv fast float [[TMP1]], [[Z]]
+; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[R:%.*]] = fadd fast float [[T1]], [[T2]]
 ; CHECK-NEXT:    call void @use(float [[T1]])
-; CHECK-NEXT:    ret float [[TMP2]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fdiv fast float %x, %z
   %t2 = fdiv fast float %y, %z
@@ -413,16 +392,15 @@ define float @fdiv_fadd_uses1(float %x,
   ret float %r
 }
 
-; FIXME:
 ; Negative test - extra uses should disable the fold.
 
 define float @fdiv_fsub_uses2(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fdiv_fsub_uses2(
-; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast float [[X:%.*]], [[Y]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fdiv fast float [[TMP1]], [[Z]]
+; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[R:%.*]] = fsub fast float [[T1]], [[T2]]
 ; CHECK-NEXT:    call void @use(float [[T2]])
-; CHECK-NEXT:    ret float [[TMP2]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fdiv fast float %x, %z
   %t2 = fdiv fast float %y, %z
@@ -431,18 +409,16 @@ define float @fdiv_fsub_uses2(float %x,
   ret float %r
 }
 
-; FIXME:
 ; Negative test - extra uses should disable the fold.
 
 define float @fdiv_fsub_uses3(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fdiv_fsub_uses3(
 ; CHECK-NEXT:    [[T1:%.*]] = fdiv fast float [[X:%.*]], [[Z:%.*]]
 ; CHECK-NEXT:    [[T2:%.*]] = fdiv fast float [[Y:%.*]], [[Z]]
-; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast float [[X]], [[Y]]
-; CHECK-NEXT:    [[TMP2:%.*]] = fdiv fast float [[TMP1]], [[Z]]
+; CHECK-NEXT:    [[R:%.*]] = fsub fast float [[T1]], [[T2]]
 ; CHECK-NEXT:    call void @use(float [[T1]])
 ; CHECK-NEXT:    call void @use(float [[T2]])
-; CHECK-NEXT:    ret float [[TMP2]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fdiv fast float %x, %z
   %t2 = fdiv fast float %y, %z
@@ -456,8 +432,8 @@ define float @fdiv_fsub_uses3(float %x,
 
 define float @fdiv_fadd_not_denorm(float %x) {
 ; CHECK-LABEL: @fdiv_fadd_not_denorm(
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv fast float 0x3818000000000000, [[X:%.*]]
-; CHECK-NEXT:    ret float [[TMP1]]
+; CHECK-NEXT:    [[R:%.*]] = fdiv fast float 0x3818000000000000, [[X:%.*]]
+; CHECK-NEXT:    ret float [[R]]
 ;
   %t1 = fdiv fast float 0x3810000000000000, %x
   %t2 = fdiv fast float 0x3800000000000000, %x




More information about the llvm-commits mailing list