<div dir="ltr">Hi Chad,<div><br></div><div>After more digging, I found out that floating-point factorization is indeed ok for fast-math operations.</div><div><br></div><div>The attached patch should fix the mixing of regular and fast operations without break fast-math factorization.</div><div><br></div><div>Best,</div><div><br></div><div>Mehdi</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">2014-11-05 23:09 GMT-08:00 Mehdi Amini <span dir="ltr"><<a href="mailto:joker.eph@gmail.com" target="_blank">joker.eph@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Chad,<br>
<br>
This commit does not only bring reassociation but also factorization, which I am not sure is allowed for floating point even in fast-math.<br>
The attached patch disables floating point refactorization while keeping reassociation.<br>
<br>
Moreover I have a crash currently when mixing fast and regular operation, see test/Transforms/Reassociate/<u></u>mixed-fast-nonfast-fp.ll in the patch.<br>
<br>
Best,<br>
<br>
Mehdi<br>
<br>
<br>
<br>
<br>
On 8/14/14, 8:23 AM, Chad Rosier wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: mcrosier<br>
Date: Thu Aug 14 10:23:01 2014<br>
New Revision: 215647<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=215647&view=rev" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project?rev=215647&view=rev</a><br>
Log:<br>
[Reassociation] Add support for reassociation with unsafe algebra.<br>
<br>
Vector instructions are (still) not supported for either integer or floating<br>
point.  Hopefully, that work will be landed shortly.<br>
<br>
Added:<br>
     llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>AgressiveSubMove.ll<br>
     llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>ArrayOutOfBounds.ll<br>
     llvm/trunk/test/Transforms/<u></u>Reassociate/fast-MissedTree.ll<br>
     llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>ReassociateVector.ll<br>
     llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>SubReassociate.ll<br>
     llvm/trunk/test/Transforms/<u></u>Reassociate/fast-basictest.ll<br>
     llvm/trunk/test/Transforms/<u></u>Reassociate/fast-fp-commute.ll<br>
     llvm/trunk/test/Transforms/<u></u>Reassociate/fast-mightymul.ll<br>
     llvm/trunk/test/Transforms/<u></u>Reassociate/fast-multistep.ll<br>
Modified:<br>
     llvm/trunk/lib/Transforms/<u></u>Scalar/Reassociate.cpp<br>
<br>
Modified: llvm/trunk/lib/Transforms/<u></u>Scalar/Reassociate.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp?rev=215647&r1=215646&r2=215647&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/lib/<u></u>Transforms/Scalar/Reassociate.<u></u>cpp?rev=215647&r1=215646&r2=<u></u>215647&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/lib/Transforms/<u></u>Scalar/Reassociate.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/<u></u>Scalar/Reassociate.cpp Thu Aug 14 10:23:01 2014<br>
@@ -240,6 +240,15 @@ static BinaryOperator *isReassociableOp(<br>
    return nullptr;<br>
  }<br>
  +static BinaryOperator *isReassociableOp(Value *V, unsigned Opcode1,<br>
+                                        unsigned Opcode2) {<br>
+  if (V->hasOneUse() && isa<Instruction>(V) &&<br>
+      (cast<Instruction>(V)-><u></u>getOpcode() == Opcode1 ||<br>
+       cast<Instruction>(V)-><u></u>getOpcode() == Opcode2))<br>
+    return cast<BinaryOperator>(V);<br>
+  return nullptr;<br>
+}<br>
+<br>
  static bool isUnmovableInstruction(<u></u>Instruction *I) {<br>
    switch (I->getOpcode()) {<br>
    case Instruction::PHI:<br>
@@ -304,8 +313,10 @@ unsigned Reassociate::getRank(Value *V)<br>
      // If this is a not or neg instruction, do not count it for rank.  This<br>
    // assures us that X and ~X will have the same rank.<br>
-  if (!I->getType()->isIntegerTy() ||<br>
-      (!BinaryOperator::isNot(I) && !BinaryOperator::isNeg(I)))<br>
+  Type *Ty = V->getType();<br>
+  if ((!Ty->isIntegerTy() && !Ty->isFloatingPointTy()) ||<br>
+      (!BinaryOperator::isNot(I) && !BinaryOperator::isNeg(I) &&<br>
+       !BinaryOperator::isFNeg(I)))<br>
      ++Rank;<br>
      //DEBUG(dbgs() << "Calculated Rank[" << V->getName() << "] = "<br>
@@ -314,14 +325,50 @@ unsigned Reassociate::getRank(Value *V)<br>
    return ValueRankMap[I] = Rank;<br>
  }<br>
  +static BinaryOperator *CreateAdd(Value *S1, Value *S2, const Twine &Name,<br>
+                                 Instruction *InsertBefore, Value *FlagsOp) {<br>
+  if (S1->getType()->isIntegerTy())<br>
+    return BinaryOperator::CreateAdd(S1, S2, Name, InsertBefore);<br>
+  else {<br>
+    BinaryOperator *Res =<br>
+        BinaryOperator::CreateFAdd(S1, S2, Name, InsertBefore);<br>
+    Res->setFastMathFlags(cast<<u></u>FPMathOperator>(FlagsOp)-><u></u>getFastMathFlags());<br>
+    return Res;<br>
+  }<br>
+}<br>
+<br>
+static BinaryOperator *CreateMul(Value *S1, Value *S2, const Twine &Name,<br>
+                                 Instruction *InsertBefore, Value *FlagsOp) {<br>
+  if (S1->getType()->isIntegerTy())<br>
+    return BinaryOperator::CreateMul(S1, S2, Name, InsertBefore);<br>
+  else {<br>
+    BinaryOperator *Res =<br>
+      BinaryOperator::CreateFMul(S1, S2, Name, InsertBefore);<br>
+    Res->setFastMathFlags(cast<<u></u>FPMathOperator>(FlagsOp)-><u></u>getFastMathFlags());<br>
+    return Res;<br>
+  }<br>
+}<br>
+<br>
+static BinaryOperator *CreateNeg(Value *S1, const Twine &Name,<br>
+                                 Instruction *InsertBefore, Value *FlagsOp) {<br>
+  if (S1->getType()->isIntegerTy())<br>
+    return BinaryOperator::CreateNeg(S1, Name, InsertBefore);<br>
+  else {<br>
+    BinaryOperator *Res = BinaryOperator::CreateFNeg(S1, Name, InsertBefore);<br>
+    Res->setFastMathFlags(cast<<u></u>FPMathOperator>(FlagsOp)-><u></u>getFastMathFlags());<br>
+    return Res;<br>
+  }<br>
+}<br>
+<br>
  /// LowerNegateToMultiply - Replace 0-X with X*-1.<br>
  ///<br>
  static BinaryOperator *LowerNegateToMultiply(<u></u>Instruction *Neg) {<br>
-  Constant *Cst = Constant::getAllOnesValue(Neg-<u></u>>getType());<br>
+  Type *Ty = Neg->getType();<br>
+  Constant *NegOne = Ty->isIntegerTy() ? ConstantInt::getAllOnesValue(<u></u>Ty)<br>
+                                       : ConstantFP::get(Ty, -1.0);<br>
  -  BinaryOperator *Res =<br>
-    BinaryOperator::CreateMul(Neg-<u></u>>getOperand(1), Cst, "",Neg);<br>
-  Neg->setOperand(1, Constant::getNullValue(Neg-><u></u>getType())); // Drop use of op.<br>
+  BinaryOperator *Res = CreateMul(Neg->getOperand(1), NegOne, "", Neg, Neg);<br>
+  Neg->setOperand(1, Constant::getNullValue(Ty)); // Drop use of op.<br>
    Res->takeName(Neg);<br>
    Neg->replaceAllUsesWith(Res);<br>
    Res->setDebugLoc(Neg-><u></u>getDebugLoc());<br>
@@ -377,13 +424,14 @@ static void IncorporateWeight(APInt &LHS<br>
      LHS = 0; // 1 + 1 === 0 modulo 2.<br>
      return;<br>
    }<br>
-  if (Opcode == Instruction::Add) {<br>
+  if (Opcode == Instruction::Add || Opcode == Instruction::FAdd) {<br>
      // TODO: Reduce the weight by exploiting nsw/nuw?<br>
      LHS += RHS;<br>
      return;<br>
    }<br>
  -  assert(Opcode == Instruction::Mul && "Unknown associative operation!");<br>
+  assert((Opcode == Instruction::Mul || Opcode == Instruction::FMul) &&<br>
+         "Unknown associative operation!");<br>
    unsigned Bitwidth = LHS.getBitWidth();<br>
    // If CM is the Carmichael number then a weight W satisfying W >= CM+Bitwidth<br>
    // can be replaced with W-CM.  That's because x^W=x^(W-CM) for every Bitwidth<br>
@@ -499,8 +547,7 @@ static bool LinearizeExprTree(BinaryOper<br>
    DEBUG(dbgs() << "LINEARIZE: " << *I << '\n');<br>
    unsigned Bitwidth = I->getType()->getScalarType()-<u></u>>getPrimitiveSizeInBits();<br>
    unsigned Opcode = I->getOpcode();<br>
-  assert(Instruction::<u></u>isAssociative(Opcode) &&<br>
-         Instruction::isCommutative(<u></u>Opcode) &&<br>
+  assert(I->isAssociative() && I->isCommutative() &&<br>
           "Expected an associative and commutative operation!");<br>
      // Visit all operands of the expression, keeping track of their weight (the<br>
@@ -619,15 +666,16 @@ static bool LinearizeExprTree(BinaryOper<br>
          // If this is a multiply expression, turn any internal negations into<br>
        // multiplies by -1 so they can be reassociated.<br>
-      BinaryOperator *BO = dyn_cast<BinaryOperator>(Op);<br>
-      if (Opcode == Instruction::Mul && BO && BinaryOperator::isNeg(BO)) {<br>
-        DEBUG(dbgs() << "MORPH LEAF: " << *Op << " (" << Weight << ") TO ");<br>
-        BO = LowerNegateToMultiply(BO);<br>
-        DEBUG(dbgs() << *BO << 'n');<br>
-        Worklist.push_back(std::make_<u></u>pair(BO, Weight));<br>
-        MadeChange = true;<br>
-        continue;<br>
-      }<br>
+      if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op))<br>
+        if ((Opcode == Instruction::Mul && BinaryOperator::isNeg(BO)) ||<br>
+            (Opcode == Instruction::FMul && BinaryOperator::isFNeg(BO))) {<br>
+          DEBUG(dbgs() << "MORPH LEAF: " << *Op << " (" << Weight << ") TO ");<br>
+          BO = LowerNegateToMultiply(BO);<br>
+          DEBUG(dbgs() << *BO << '\n');<br>
+          Worklist.push_back(std::make_<u></u>pair(BO, Weight));<br>
+          MadeChange = true;<br>
+          continue;<br>
+        }<br>
          // Failed to morph into an expression of the right type.  This really is<br>
        // a leaf.<br>
@@ -798,6 +846,8 @@ void Reassociate::RewriteExprTree(<u></u>Binary<br>
        Constant *Undef = UndefValue::get(I->getType());<br>
        NewOp = BinaryOperator::Create(<u></u>Instruction::BinaryOps(Opcode)<u></u>,<br>
                                       Undef, Undef, "", I);<br>
+      if (NewOp->getType()-><u></u>isFloatingPointTy())<br>
+        NewOp->setFastMathFlags(I-><u></u>getFastMathFlags());<br>
      } else {<br>
        NewOp = NodesToRewrite.pop_back_val();<br>
      }<br>
@@ -817,7 +867,14 @@ void Reassociate::RewriteExprTree(<u></u>Binary<br>
    // expression tree is dominated by all of Ops.<br>
    if (ExpressionChanged)<br>
      do {<br>
-      ExpressionChanged-><u></u>clearSubclassOptionalData();<br>
+      // Preserve FastMathFlags.<br>
+      if (isa<FPMathOperator>(I)) {<br>
+        FastMathFlags Flags = I->getFastMathFlags();<br>
+        ExpressionChanged-><u></u>clearSubclassOptionalData();<br>
+        ExpressionChanged-><u></u>setFastMathFlags(Flags);<br>
+      } else<br>
+        ExpressionChanged-><u></u>clearSubclassOptionalData();<br>
+<br>
        if (ExpressionChanged == I)<br>
          break;<br>
        ExpressionChanged->moveBefore(<u></u>I);<br>
@@ -834,6 +891,8 @@ void Reassociate::RewriteExprTree(<u></u>Binary<br>
  /// version of the value is returned, and BI is left pointing at the instruction<br>
  /// that should be processed next by the reassociation pass.<br>
  static Value *NegateValue(Value *V, Instruction *BI) {<br>
+  if (ConstantFP *C = dyn_cast<ConstantFP>(V))<br>
+    return ConstantExpr::getFNeg(C);<br>
    if (Constant *C = dyn_cast<Constant>(V))<br>
      return ConstantExpr::getNeg(C);<br>
  @@ -846,7 +905,8 @@ static Value *NegateValue(Value *V, Inst<br>
    // the constants.  We assume that instcombine will clean up the mess later if<br>
    // we introduce tons of unnecessary negation instructions.<br>
    //<br>
-  if (BinaryOperator *I = isReassociableOp(V, Instruction::Add)) {<br>
+  if (BinaryOperator *I =<br>
+          isReassociableOp(V, Instruction::Add, Instruction::FAdd)) {<br>
      // Push the negates through the add.<br>
      I->setOperand(0, NegateValue(I->getOperand(0), BI));<br>
      I->setOperand(1, NegateValue(I->getOperand(1), BI));<br>
@@ -864,7 +924,8 @@ static Value *NegateValue(Value *V, Inst<br>
    // Okay, we need to materialize a negated version of V with an instruction.<br>
    // Scan the use lists of V to see if we have one already.<br>
    for (User *U : V->users()) {<br>
-    if (!BinaryOperator::isNeg(U)) continue;<br>
+    if (!BinaryOperator::isNeg(U) && !BinaryOperator::isFNeg(U))<br>
+      continue;<br>
        // We found one!  Now we have to make sure that the definition dominates<br>
      // this use.  We do this by moving it to the entry block (if it is a<br>
@@ -894,27 +955,30 @@ static Value *NegateValue(Value *V, Inst<br>
      // Insert a 'neg' instruction that subtracts the value from zero to get the<br>
    // negation.<br>
-  return BinaryOperator::CreateNeg(V, V->getName() + ".neg", BI);<br>
+  return CreateNeg(V, V->getName() + ".neg", BI, BI);<br>
  }<br>
    /// ShouldBreakUpSubtract - Return true if we should break up this subtract of<br>
  /// X-Y into (X + -Y).<br>
  static bool ShouldBreakUpSubtract(<u></u>Instruction *Sub) {<br>
    // If this is a negation, we can't split it up!<br>
-  if (BinaryOperator::isNeg(Sub))<br>
+  if (BinaryOperator::isNeg(Sub) || BinaryOperator::isFNeg(Sub))<br>
      return false;<br>
      // Don't bother to break this up unless either the LHS is an associable add or<br>
    // subtract or if this is only used by one.<br>
-  if (isReassociableOp(Sub-><u></u>getOperand(0), Instruction::Add) ||<br>
-      isReassociableOp(Sub-><u></u>getOperand(0), Instruction::Sub))<br>
+  Value *V0 = Sub->getOperand(0);<br>
+  if (isReassociableOp(V0, Instruction::Add, Instruction::FAdd) ||<br>
+      isReassociableOp(V0, Instruction::Sub, Instruction::FSub))<br>
      return true;<br>
-  if (isReassociableOp(Sub-><u></u>getOperand(1), Instruction::Add) ||<br>
-      isReassociableOp(Sub-><u></u>getOperand(1), Instruction::Sub))<br>
+  Value *V1 = Sub->getOperand(1);<br>
+  if (isReassociableOp(V1, Instruction::Add, Instruction::FAdd) ||<br>
+      isReassociableOp(V1, Instruction::Sub, Instruction::FSub))<br>
      return true;<br>
+  Value *VB = Sub->user_back();<br>
    if (Sub->hasOneUse() &&<br>
-      (isReassociableOp(Sub->user_<u></u>back(), Instruction::Add) ||<br>
-       isReassociableOp(Sub->user_<u></u>back(), Instruction::Sub)))<br>
+      (isReassociableOp(VB, Instruction::Add, Instruction::FAdd) ||<br>
+       isReassociableOp(VB, Instruction::Sub, Instruction::FSub)))<br>
      return true;<br>
      return false;<br>
@@ -931,8 +995,7 @@ static BinaryOperator *BreakUpSubtract(I<br>
    // and set it as the RHS of the add instruction we just made.<br>
    //<br>
    Value *NegVal = NegateValue(Sub->getOperand(1)<u></u>, Sub);<br>
-  BinaryOperator *New =<br>
-    BinaryOperator::CreateAdd(Sub-<u></u>>getOperand(0), NegVal, "", Sub);<br>
+  BinaryOperator *New = CreateAdd(Sub->getOperand(0), NegVal, "", Sub, Sub);<br>
    Sub->setOperand(0, Constant::getNullValue(Sub-><u></u>getType())); // Drop use of op.<br>
    Sub->setOperand(1, Constant::getNullValue(Sub-><u></u>getType())); // Drop use of op.<br>
    New->takeName(Sub);<br>
@@ -988,15 +1051,16 @@ static Value *EmitAddTreeOfValues(Instru<br>
    Value *V1 = Ops.back();<br>
    Ops.pop_back();<br>
    Value *V2 = EmitAddTreeOfValues(I, Ops);<br>
-  return BinaryOperator::CreateAdd(V2, V1, "tmp", I);<br>
+  return CreateAdd(V2, V1, "tmp", I, I);<br>
  }<br>
    /// RemoveFactorFromExpression - If V is an expression tree that is a<br>
  /// multiplication sequence, and if this sequence contains a multiply by Factor,<br>
  /// remove Factor from the tree and return the new tree.<br>
  Value *Reassociate::<u></u>RemoveFactorFromExpression(<u></u>Value *V, Value *Factor) {<br>
-  BinaryOperator *BO = isReassociableOp(V, Instruction::Mul);<br>
-  if (!BO) return nullptr;<br>
+  BinaryOperator *BO = isReassociableOp(V, Instruction::Mul, Instruction::FMul);<br>
+  if (!BO)<br>
+    return nullptr;<br>
      SmallVector<RepeatedValue, 8> Tree;<br>
    MadeChange |= LinearizeExprTree(BO, Tree);<br>
@@ -1018,13 +1082,25 @@ Value *Reassociate::<u></u>RemoveFactorFromExpr<br>
      }<br>
        // If this is a negative version of this factor, remove it.<br>
-    if (ConstantInt *FC1 = dyn_cast<ConstantInt>(Factor))<br>
+    if (ConstantInt *FC1 = dyn_cast<ConstantInt>(Factor)) {<br>
        if (ConstantInt *FC2 = dyn_cast<ConstantInt>(Factors[<u></u>i].Op))<br>
          if (FC1->getValue() == -FC2->getValue()) {<br>
            FoundFactor = NeedsNegate = true;<br>
            Factors.erase(Factors.begin()+<u></u>i);<br>
            break;<br>
          }<br>
+    } else if (ConstantFP *FC1 = dyn_cast<ConstantFP>(Factor)) {<br>
+      if (ConstantFP *FC2 = dyn_cast<ConstantFP>(Factors[<u></u>i].Op)) {<br>
+        APFloat F1(FC1->getValueAPF());<br>
+        APFloat F2(FC2->getValueAPF());<br>
+        F2.changeSign();<br>
+        if (F1.compare(F2) == APFloat::cmpEqual) {<br>
+          FoundFactor = NeedsNegate = true;<br>
+          Factors.erase(Factors.begin() + i);<br>
+          break;<br>
+        }<br>
+      }<br>
+    }<br>
    }<br>
      if (!FoundFactor) {<br>
@@ -1046,7 +1122,7 @@ Value *Reassociate::<u></u>RemoveFactorFromExpr<br>
    }<br>
      if (NeedsNegate)<br>
-    V = BinaryOperator::CreateNeg(V, "neg", InsertPt);<br>
+    V = CreateNeg(V, "neg", InsertPt, BO);<br>
      return V;<br>
  }<br>
@@ -1058,7 +1134,7 @@ Value *Reassociate::<u></u>RemoveFactorFromExpr<br>
  static void FindSingleUseMultiplyFactors(<u></u>Value *V,<br>
                                           SmallVectorImpl<Value*> &Factors,<br>
                                         const SmallVectorImpl<ValueEntry> &Ops) {<br>
-  BinaryOperator *BO = isReassociableOp(V, Instruction::Mul);<br>
+  BinaryOperator *BO = isReassociableOp(V, Instruction::Mul, Instruction::FMul);<br>
    if (!BO) {<br>
      Factors.push_back(V);<br>
      return;<br>
@@ -1389,13 +1465,15 @@ Value *Reassociate::OptimizeAdd(<u></u>Instruct<br>
        ++NumFactor;<br>
          // Insert a new multiply.<br>
-      Value *Mul = ConstantInt::get(cast<<u></u>IntegerType>(I->getType()), NumFound);<br>
-      Mul = BinaryOperator::CreateMul(<u></u>TheOp, Mul, "factor", I);<br>
+      Type *Ty = TheOp->getType();<br>
+      Constant *C = Ty->isIntegerTy() ? ConstantInt::get(Ty, NumFound)<br>
+                                      : ConstantFP::get(Ty, NumFound);<br>
+      Instruction *Mul = CreateMul(TheOp, C, "factor", I, I);<br>
          // Now that we have inserted a multiply, optimize it. This allows us to<br>
        // handle cases that require multiple factoring steps, such as this:<br>
        // (X*2) + (X*2) + (X*2) -> (X*2)*3 -> X*6<br>
-      RedoInsts.insert(cast<<u></u>Instruction>(Mul));<br>
+      RedoInsts.insert(Mul);<br>
          // If every add operand was a duplicate, return the multiply.<br>
        if (Ops.empty())<br>
@@ -1412,11 +1490,12 @@ Value *Reassociate::OptimizeAdd(<u></u>Instruct<br>
      }<br>
        // Check for X and -X or X and ~X in the operand list.<br>
-    if (!BinaryOperator::isNeg(TheOp) && !BinaryOperator::isNot(TheOp))<br>
+    if (!BinaryOperator::isNeg(TheOp) && !BinaryOperator::isFNeg(TheOp) &&<br>
+        !BinaryOperator::isNot(TheOp))<br>
        continue;<br>
        Value *X = nullptr;<br>
-    if (BinaryOperator::isNeg(TheOp))<br>
+    if (BinaryOperator::isNeg(TheOp) || BinaryOperator::isFNeg(TheOp))<br>
        X = BinaryOperator::<u></u>getNegArgument(TheOp);<br>
      else if (BinaryOperator::isNot(TheOp))<br>
        X = BinaryOperator::<u></u>getNotArgument(TheOp);<br>
@@ -1426,7 +1505,8 @@ Value *Reassociate::OptimizeAdd(<u></u>Instruct<br>
        continue;<br>
        // Remove X and -X from the operand list.<br>
-    if (Ops.size() == 2 && BinaryOperator::isNeg(TheOp))<br>
+    if (Ops.size() == 2 &&<br>
+        (BinaryOperator::isNeg(TheOp) || BinaryOperator::isFNeg(TheOp))<u></u>)<br>
        return Constant::getNullValue(X-><u></u>getType());<br>
        // Remove X and ~X from the operand list.<br>
@@ -1463,7 +1543,8 @@ Value *Reassociate::OptimizeAdd(<u></u>Instruct<br>
    unsigned MaxOcc = 0;<br>
    Value *MaxOccVal = nullptr;<br>
    for (unsigned i = 0, e = Ops.size(); i != e; ++i) {<br>
-    BinaryOperator *BOp = isReassociableOp(Ops[i].Op, Instruction::Mul);<br>
+    BinaryOperator *BOp =<br>
+        isReassociableOp(Ops[i].Op, Instruction::Mul, Instruction::FMul);<br>
      if (!BOp)<br>
        continue;<br>
  @@ -1476,23 +1557,43 @@ Value *Reassociate::OptimizeAdd(<u></u>Instruct<br>
      SmallPtrSet<Value*, 8> Duplicates;<br>
      for (unsigned i = 0, e = Factors.size(); i != e; ++i) {<br>
        Value *Factor = Factors[i];<br>
-      if (!Duplicates.insert(Factor)) continue;<br>
+      if (!Duplicates.insert(Factor))<br>
+        continue;<br>
          unsigned Occ = ++FactorOccurrences[Factor];<br>
-      if (Occ > MaxOcc) { MaxOcc = Occ; MaxOccVal = Factor; }<br>
+      if (Occ > MaxOcc) {<br>
+        MaxOcc = Occ;<br>
+        MaxOccVal = Factor;<br>
+      }<br>
          // If Factor is a negative constant, add the negated value as a factor<br>
        // because we can percolate the negate out.  Watch for minint, which<br>
        // cannot be positivified.<br>
-      if (ConstantInt *CI = dyn_cast<ConstantInt>(Factor))<br>
+      if (ConstantInt *CI = dyn_cast<ConstantInt>(Factor)) {<br>
          if (CI->isNegative() && !CI->isMinValue(true)) {<br>
            Factor = ConstantInt::get(CI-><u></u>getContext(), -CI->getValue());<br>
            assert(!Duplicates.count(<u></u>Factor) &&<br>
                   "Shouldn't have two constant factors, missed a canonicalize");<br>
-<br>
            unsigned Occ = ++FactorOccurrences[Factor];<br>
-          if (Occ > MaxOcc) { MaxOcc = Occ; MaxOccVal = Factor; }<br>
+          if (Occ > MaxOcc) {<br>
+            MaxOcc = Occ;<br>
+            MaxOccVal = Factor;<br>
+          }<br>
          }<br>
+      } else if (ConstantFP *CF = dyn_cast<ConstantFP>(Factor)) {<br>
+        if (CF->isNegative()) {<br>
+          APFloat F(CF->getValueAPF());<br>
+          F.changeSign();<br>
+          Factor = ConstantFP::get(CF-><u></u>getContext(), F);<br>
+          assert(!Duplicates.count(<u></u>Factor) &&<br>
+                 "Shouldn't have two constant factors, missed a canonicalize");<br>
+          unsigned Occ = ++FactorOccurrences[Factor];<br>
+          if (Occ > MaxOcc) {<br>
+            MaxOcc = Occ;<br>
+            MaxOccVal = Factor;<br>
+          }<br>
+        }<br>
+      }<br>
      }<br>
    }<br>
  @@ -1505,11 +1606,16 @@ Value *Reassociate::OptimizeAdd(<u></u>Instruct<br>
      // this, we could otherwise run into situations where removing a factor<br>
      // from an expression will drop a use of maxocc, and this can cause<br>
      // RemoveFactorFromExpression on successive values to behave differently.<br>
-    Instruction *DummyInst = BinaryOperator::CreateAdd(<u></u>MaxOccVal, MaxOccVal);<br>
+    Instruction *DummyInst =<br>
+        I->getType()->isIntegerTy()<br>
+            ? BinaryOperator::CreateAdd(<u></u>MaxOccVal, MaxOccVal)<br>
+            : BinaryOperator::CreateFAdd(<u></u>MaxOccVal, MaxOccVal);<br>
+<br>
      SmallVector<WeakVH, 4> NewMulOps;<br>
      for (unsigned i = 0; i != Ops.size(); ++i) {<br>
        // Only try to remove factors from expressions we're allowed to.<br>
-      BinaryOperator *BOp = isReassociableOp(Ops[i].Op, Instruction::Mul);<br>
+      BinaryOperator *BOp =<br>
+          isReassociableOp(Ops[i].Op, Instruction::Mul, Instruction::FMul);<br>
        if (!BOp)<br>
          continue;<br>
  @@ -1542,7 +1648,7 @@ Value *Reassociate::OptimizeAdd(<u></u>Instruct<br>
        RedoInsts.insert(VI);<br>
        // Create the multiply.<br>
-    Instruction *V2 = BinaryOperator::CreateMul(V, MaxOccVal, "tmp", I);<br>
+    Instruction *V2 = CreateMul(V, MaxOccVal, "tmp", I, I);<br>
        // Rerun associate on the multiply in case the inner expression turned into<br>
      // a multiply.  We want to make sure that we keep things in canonical form.<br>
@@ -1632,7 +1738,10 @@ static Value *buildMultiplyTree(IRBuilde<br>
      Value *LHS = Ops.pop_back_val();<br>
    do {<br>
-    LHS = Builder.CreateMul(LHS, Ops.pop_back_val());<br>
+    if (LHS->getType()->isIntegerTy()<u></u>)<br>
+      LHS = Builder.CreateMul(LHS, Ops.pop_back_val());<br>
+    else<br>
+      LHS = Builder.CreateFMul(LHS, Ops.pop_back_val());<br>
    } while (!Ops.empty());<br>
      return LHS;<br>
@@ -1765,11 +1874,13 @@ Value *Reassociate::<u></u>OptimizeExpression(B<br>
      break;<br>
      case Instruction::Add:<br>
+  case Instruction::FAdd:<br>
      if (Value *Result = OptimizeAdd(I, Ops))<br>
        return Result;<br>
      break;<br>
      case Instruction::Mul:<br>
+  case Instruction::FMul:<br>
      if (Value *Result = OptimizeMul(I, Ops))<br>
        return Result;<br>
      break;<br>
@@ -1810,8 +1921,7 @@ void Reassociate::OptimizeInst(<u></u>Instructi<br>
    if (!isa<BinaryOperator>(I))<br>
      return;<br>
  -  if (I->getOpcode() == Instruction::Shl &&<br>
-      isa<ConstantInt>(I-><u></u>getOperand(1)))<br>
+  if (I->getOpcode() == Instruction::Shl && isa<ConstantInt>(I-><u></u>getOperand(1)))<br>
      // If an operand of this shift is a reassociable multiply, or if the shift<br>
      // is used by a reassociable multiply or add, turn into a multiply.<br>
      if (isReassociableOp(I-><u></u>getOperand(0), Instruction::Mul) ||<br>
@@ -1824,28 +1934,33 @@ void Reassociate::OptimizeInst(<u></u>Instructi<br>
        I = NI;<br>
      }<br>
  -  // Floating point binary operators are not associative, but we can still<br>
-  // commute (some) of them, to canonicalize the order of their operands.<br>
-  // This can potentially expose more CSE opportunities, and makes writing<br>
-  // other transformations simpler.<br>
-  if ((I->getType()-><u></u>isFloatingPointTy() || I->getType()->isVectorTy())) {<br>
-    // FAdd and FMul can be commuted.<br>
-    if (I->getOpcode() != Instruction::FMul &&<br>
-        I->getOpcode() != Instruction::FAdd)<br>
-      return;<br>
+  // Commute floating point binary operators, to canonicalize the order of their<br>
+  // operands.  This can potentially expose more CSE opportunities, and makes<br>
+  // writing other transformations simpler.<br>
+  if (I->getType()-><u></u>isFloatingPointTy() || I->getType()->isVectorTy()) {<br>
  -    Value *LHS = I->getOperand(0);<br>
-    Value *RHS = I->getOperand(1);<br>
-    unsigned LHSRank = getRank(LHS);<br>
-    unsigned RHSRank = getRank(RHS);<br>
-<br>
-    // Sort the operands by rank.<br>
-    if (RHSRank < LHSRank) {<br>
-      I->setOperand(0, RHS);<br>
-      I->setOperand(1, LHS);<br>
+    // FAdd and FMul can be commuted.<br>
+    if (I->getOpcode() == Instruction::FMul ||<br>
+        I->getOpcode() == Instruction::FAdd) {<br>
+      Value *LHS = I->getOperand(0);<br>
+      Value *RHS = I->getOperand(1);<br>
+      unsigned LHSRank = getRank(LHS);<br>
+      unsigned RHSRank = getRank(RHS);<br>
+<br>
+      // Sort the operands by rank.<br>
+      if (RHSRank < LHSRank) {<br>
+        I->setOperand(0, RHS);<br>
+        I->setOperand(1, LHS);<br>
+      }<br>
      }<br>
  -    return;<br>
+    // FIXME: We should commute vector instructions as well.  However, this<br>
+    // requires further analysis to determine the effect on later passes.<br>
+<br>
+    // Don't try to optimize vector instructions or anything that doesn't have<br>
+    // unsafe algebra.<br>
+    if (I->getType()->isVectorTy() || !I->hasUnsafeAlgebra())<br>
+      return;<br>
    }<br>
      // Do not reassociate boolean (i1) expressions.  We want to preserve the<br>
@@ -1877,6 +1992,24 @@ void Reassociate::OptimizeInst(<u></u>Instructi<br>
          I = NI;<br>
        }<br>
      }<br>
+  } else if (I->getOpcode() == Instruction::FSub) {<br>
+    if (ShouldBreakUpSubtract(I)) {<br>
+      Instruction *NI = BreakUpSubtract(I);<br>
+      RedoInsts.insert(I);<br>
+      MadeChange = true;<br>
+      I = NI;<br>
+    } else if (BinaryOperator::isFNeg(I)) {<br>
+      // Otherwise, this is a negation.  See if the operand is a multiply tree<br>
+      // and if this is not an inner node of a multiply tree.<br>
+      if (isReassociableOp(I-><u></u>getOperand(1), Instruction::FMul) &&<br>
+          (!I->hasOneUse() ||<br>
+           !isReassociableOp(I->user_<u></u>back(), Instruction::FMul))) {<br>
+        Instruction *NI = LowerNegateToMultiply(I);<br>
+        RedoInsts.insert(I);<br>
+        MadeChange = true;<br>
+        I = NI;<br>
+      }<br>
+    }<br>
    }<br>
      // If this instruction is an associative binary operator, process it.<br>
@@ -1894,11 +2027,16 @@ void Reassociate::OptimizeInst(<u></u>Instructi<br>
    if (BO->hasOneUse() && BO->getOpcode() == Instruction::Add &&<br>
        cast<Instruction>(BO->user_<u></u>back())->getOpcode() == Instruction::Sub)<br>
      return;<br>
+  if (BO->hasOneUse() && BO->getOpcode() == Instruction::FAdd &&<br>
+      cast<Instruction>(BO->user_<u></u>back())->getOpcode() == Instruction::FSub)<br>
+    return;<br>
      ReassociateExpression(BO);<br>
  }<br>
    void Reassociate::<u></u>ReassociateExpression(<u></u>BinaryOperator *I) {<br>
+  assert(!I->getType()-><u></u>isVectorTy() &&<br>
+         "Reassociation of vector instructions is not supported.");<br>
      // First, walk the expression tree, linearizing the tree, collecting the<br>
    // operand information.<br>
@@ -1943,12 +2081,21 @@ void Reassociate::<u></u>ReassociateExpression(<br>
    // this is a multiply tree used only by an add, and the immediate is a -1.<br>
    // In this case we reassociate to put the negation on the outside so that we<br>
    // can fold the negation into the add: (-X)*Y + Z -> Z-X*Y<br>
-  if (I->getOpcode() == Instruction::Mul && I->hasOneUse() &&<br>
-      cast<Instruction>(I->user_<u></u>back())->getOpcode() == Instruction::Add &&<br>
-      isa<ConstantInt>(Ops.back().<u></u>Op) &&<br>
-      cast<ConstantInt>(Ops.back().<u></u>Op)->isAllOnesValue()) {<br>
-    ValueEntry Tmp = Ops.pop_back_val();<br>
-    Ops.insert(Ops.begin(), Tmp);<br>
+  if (I->hasOneUse()) {<br>
+    if (I->getOpcode() == Instruction::Mul &&<br>
+        cast<Instruction>(I->user_<u></u>back())->getOpcode() == Instruction::Add &&<br>
+        isa<ConstantInt>(Ops.back().<u></u>Op) &&<br>
+        cast<ConstantInt>(Ops.back().<u></u>Op)->isAllOnesValue()) {<br>
+      ValueEntry Tmp = Ops.pop_back_val();<br>
+      Ops.insert(Ops.begin(), Tmp);<br>
+    } else if (I->getOpcode() == Instruction::FMul &&<br>
+               cast<Instruction>(I->user_<u></u>back())->getOpcode() ==<br>
+                   Instruction::FAdd &&<br>
+               isa<ConstantFP>(Ops.back().Op) &&<br>
+               cast<ConstantFP>(Ops.back().<u></u>Op)->isExactlyValue(-1.0)) {<br>
+      ValueEntry Tmp = Ops.pop_back_val();<br>
+      Ops.insert(Ops.begin(), Tmp);<br>
+    }<br>
    }<br>
      DEBUG(dbgs() << "RAOut:\t"; PrintOps(I, Ops); dbgs() << '\n');<br>
<br>
Added: llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>AgressiveSubMove.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/fast-AgressiveSubMove.ll?rev=215647&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>Transforms/Reassociate/fast-<u></u>AgressiveSubMove.ll?rev=<u></u>215647&view=auto</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>AgressiveSubMove.ll (added)<br>
+++ llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>AgressiveSubMove.ll Thu Aug 14 10:23:01 2014<br>
@@ -0,0 +1,24 @@<br>
+; RUN: opt < %s -reassociate -S | FileCheck %s<br>
+<br>
+define float @test1(float %A) {<br>
+; CHECK-LABEL: test1<br>
+; CHECK-NEXT: %X = fadd float 1.000000e+00, %A<br>
+; CHECK-NEXT: %Y = fadd float 1.000000e+00, %A<br>
+; CHECK-NEXT: %r = fsub float %X, %Y<br>
+; CHECK-NEXT: ret float %r<br>
+<br>
+  %X = fadd float %A, 1.000000e+00<br>
+  %Y = fadd float %A, 1.000000e+00<br>
+  %r = fsub float %X, %Y<br>
+  ret float %r<br>
+}<br>
+<br>
+define float @test2(float %A) {<br>
+; CHECK-LABEL: test2<br>
+; CHECK-NEXT: ret float 0.000000e+00<br>
+<br>
+  %X = fadd fast float 1.000000e+00, %A<br>
+  %Y = fadd fast float 1.000000e+00, %A<br>
+  %r = fsub fast float %X, %Y<br>
+  ret float %r<br>
+}<br>
<br>
Added: llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>ArrayOutOfBounds.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/fast-ArrayOutOfBounds.ll?rev=215647&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>Transforms/Reassociate/fast-<u></u>ArrayOutOfBounds.ll?rev=<u></u>215647&view=auto</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>ArrayOutOfBounds.ll (added)<br>
+++ llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>ArrayOutOfBounds.ll Thu Aug 14 10:23:01 2014<br>
@@ -0,0 +1,65 @@<br>
+; RUN: opt < %s -reassociate -instcombine -S | FileCheck %s<br>
+<br>
+; Not marked as fast, so must not change.<br>
+define float @test1(float %a0, float %a1, float %a2, float %a3, float %a4) {<br>
+; CHECK-LABEL: test1<br>
+; CHECK-NEXT: %tmp.2 = fadd float %a3, %a4<br>
+; CHECK-NEXT: %tmp.4 = fadd float %tmp.2, %a2<br>
+; CHECK-NEXT: %tmp.6 = fadd float %tmp.4, %a1<br>
+; CHECK-NEXT: %tmp.8 = fadd float %tmp.6, %a0<br>
+; CHECK-NEXT: %tmp.11 = fadd float %a2, %a3<br>
+; CHECK-NEXT: %tmp.13 = fadd float %tmp.11, %a1<br>
+; CHECK-NEXT: %tmp.15 = fadd float %tmp.13, %a0<br>
+; CHECK-NEXT: %tmp.18 = fadd float %a1, %a2<br>
+; CHECK-NEXT: %tmp.20 = fadd float %tmp.18, %a0<br>
+; CHECK-NEXT: %tmp.23 = fadd float %a0, %a1<br>
+; CHECK-NEXT: %tmp.26 = fsub float %tmp.8, %tmp.15<br>
+; CHECK-NEXT: %tmp.28 = fadd float %tmp.20, %tmp.26<br>
+; CHECK-NEXT: %tmp.30 = fsub float %tmp.28, %tmp.23<br>
+; CHECK-NEXT: %tmp.32 = fsub float %tmp.30, %a4<br>
+; CHECK-NEXT: %tmp.34 = fsub float %tmp.32, %a2<br>
+; CHECK-NEXT: %T = fmul float %tmp.34, %tmp.34<br>
+; CHECK-NEXT: ret float %T<br>
+<br>
+  %tmp.2 = fadd float %a4, %a3<br>
+  %tmp.4 = fadd float %tmp.2, %a2<br>
+  %tmp.6 = fadd float %tmp.4, %a1<br>
+  %tmp.8 = fadd float %tmp.6, %a0<br>
+  %tmp.11 = fadd float %a3, %a2<br>
+  %tmp.13 = fadd float %tmp.11, %a1<br>
+  %tmp.15 = fadd float %tmp.13, %a0<br>
+  %tmp.18 = fadd float %a2, %a1<br>
+  %tmp.20 = fadd float %tmp.18, %a0<br>
+  %tmp.23 = fadd float %a1, %a0<br>
+  %tmp.26 = fsub float %tmp.8, %tmp.15<br>
+  %tmp.28 = fadd float %tmp.26, %tmp.20<br>
+  %tmp.30 = fsub float %tmp.28, %tmp.23<br>
+  %tmp.32 = fsub float %tmp.30, %a4<br>
+  %tmp.34 = fsub float %tmp.32, %a2<br>
+  %T = fmul float %tmp.34, %tmp.34<br>
+  ret float %T<br>
+}<br>
+<br>
+; Should be able to eliminate everything.<br>
+define float @test2(float %a0, float %a1, float %a2, float %a3, float %a4) {<br>
+; CHECK-LABEL: test2<br>
+; CHECK: ret float 0.000000e+00<br>
+<br>
+  %tmp.2 = fadd fast float %a4, %a3<br>
+  %tmp.4 = fadd fast float %tmp.2, %a2<br>
+  %tmp.6 = fadd fast float %tmp.4, %a1<br>
+  %tmp.8 = fadd fast float %tmp.6, %a0<br>
+  %tmp.11 = fadd fast float %a3, %a2<br>
+  %tmp.13 = fadd fast float %tmp.11, %a1<br>
+  %tmp.15 = fadd fast float %tmp.13, %a0<br>
+  %tmp.18 = fadd fast float %a2, %a1<br>
+  %tmp.20 = fadd fast float %tmp.18, %a0<br>
+  %tmp.23 = fadd fast float %a1, %a0<br>
+  %tmp.26 = fsub fast float %tmp.8, %tmp.15<br>
+  %tmp.28 = fadd fast float %tmp.26, %tmp.20<br>
+  %tmp.30 = fsub fast float %tmp.28, %tmp.23<br>
+  %tmp.32 = fsub fast float %tmp.30, %a4<br>
+  %tmp.34 = fsub fast float %tmp.32, %a2<br>
+  %T = fmul fast float %tmp.34, %tmp.34<br>
+  ret float %T<br>
+}<br>
<br>
Added: llvm/trunk/test/Transforms/<u></u>Reassociate/fast-MissedTree.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/fast-MissedTree.ll?rev=215647&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>Transforms/Reassociate/fast-<u></u>MissedTree.ll?rev=215647&view=<u></u>auto</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/Transforms/<u></u>Reassociate/fast-MissedTree.ll (added)<br>
+++ llvm/trunk/test/Transforms/<u></u>Reassociate/fast-MissedTree.ll Thu Aug 14 10:23:01 2014<br>
@@ -0,0 +1,11 @@<br>
+; RUN: opt < %s -reassociate -instcombine -S | FileCheck %s<br>
+<br>
+define float @test1(float %A, float %B) {<br>
+; CHECK-LABEL: test1<br>
+; CHECK: %Z = fadd fast float %A, %B<br>
+; CHECK: ret float %Z<br>
+       %W = fadd fast float %B, -5.0<br>
+       %Y = fadd fast float %A, 5.0<br>
+       %Z = fadd fast float %W, %Y<br>
+       ret float %Z<br>
+}<br>
<br>
Added: llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>ReassociateVector.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/fast-ReassociateVector.ll?rev=215647&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>Transforms/Reassociate/fast-<u></u>ReassociateVector.ll?rev=<u></u>215647&view=auto</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>ReassociateVector.ll (added)<br>
+++ llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>ReassociateVector.ll Thu Aug 14 10:23:01 2014<br>
@@ -0,0 +1,25 @@<br>
+; RUN: opt < %s -reassociate -S | FileCheck %s<br>
+<br>
+; Don't handle floating point vector operations.<br>
+define <4 x float> @test1() {<br>
+; CHECK-LABEL: test1<br>
+; CHECK-NEXT: %tmp1 = fsub fast <4 x float> zeroinitializer, zeroinitializer<br>
+; CHECK-NEXT: %tmp2 = fmul fast <4 x float> zeroinitializer, %tmp1<br>
+<br>
+  %tmp1 = fsub fast <4 x float> zeroinitializer, zeroinitializer<br>
+  %tmp2 = fmul fast <4 x float> zeroinitializer, %tmp1<br>
+  ret <4 x float> %tmp2<br>
+}<br>
+<br>
+; We don't currently commute integer vector operations.<br>
+define <2 x i32> @test2(<2 x i32> %x, <2 x i32> %y) {<br>
+; CHECK-LABEL: test2<br>
+; CHECK-NEXT: %tmp1 = add <2 x i32> %x, %y<br>
+; CHECK-NEXT: %tmp2 = add <2 x i32> %y, %x<br>
+; CHECK-NEXT: %tmp3 = add <2 x i32> %tmp1, %tmp2<br>
+<br>
+  %tmp1 = add <2 x i32> %x, %y<br>
+  %tmp2 = add <2 x i32> %y, %x<br>
+  %tmp3 = add <2 x i32> %tmp1, %tmp2<br>
+  ret <2 x i32> %tmp3<br>
+}<br>
<br>
Added: llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>SubReassociate.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/fast-SubReassociate.ll?rev=215647&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>Transforms/Reassociate/fast-<u></u>SubReassociate.ll?rev=215647&<u></u>view=auto</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>SubReassociate.ll (added)<br>
+++ llvm/trunk/test/Transforms/<u></u>Reassociate/fast-<u></u>SubReassociate.ll Thu Aug 14 10:23:01 2014<br>
@@ -0,0 +1,70 @@<br>
+; RUN: opt < %s -reassociate -constprop -instcombine -S | FileCheck %s<br>
+<br>
+define float @test1(float %A, float %B) {<br>
+; CHECK-LABEL: test1<br>
+; CHECK-NEXT: %W = fadd float %B, 5.000000e+00<br>
+; CHECK-NEXT: %X = fadd float %A, -7.000000e+00<br>
+; CHECK-NEXT: %Y = fsub float %X, %W<br>
+; CHECK-NEXT: %Z = fadd float %Y, 1.200000e+01<br>
+; CHECK-NEXT: ret float %Z<br>
+<br>
+  %W = fadd float 5.0, %B<br>
+  %X = fadd float -7.0, %A<br>
+  %Y = fsub float %X, %W<br>
+  %Z = fadd float %Y, 12.0<br>
+  ret float %Z<br>
+}<br>
+<br>
+; With sub reassociation, constant folding can eliminate all of the constants.<br>
+define float @test2(float %A, float %B) {<br>
+; CHECK-LABEL: test2<br>
+; CHECK-NEXT: %Z = fsub fast float %A, %B<br>
+; CHECK-NEXT: ret float %Z<br>
+<br>
+  %W = fadd fast float %B, 5.000000e+00<br>
+  %X = fadd fast float %A, -7.000000e+00<br>
+  %Y = fsub fast float %X, %W<br>
+  %Z = fadd fast float %Y, 1.200000e+01<br>
+  ret float %Z<br>
+<br>
+}<br>
+<br>
+define float @test3(float %A, float %B, float %C, float %D) {<br>
+; CHECK-LABEL: test3<br>
+; CHECK-NEXT: %M = fadd float %A, 1.200000e+01<br>
+; CHECK-NEXT: %N = fadd float %M, %B<br>
+; CHECK-NEXT: %O = fadd float %N, %C<br>
+; CHECK-NEXT: %P = fsub float %D, %O<br>
+; CHECK-NEXT: %Q = fadd float %P, 1.200000e+01<br>
+; CHECK-NEXT: ret float %Q<br>
+<br>
+  %M = fadd float %A, 1.200000e+01<br>
+  %N = fadd float %M, %B<br>
+  %O = fadd float %N, %C<br>
+  %P = fsub float %D, %O<br>
+  %Q = fadd float %P, 1.200000e+01<br>
+  ret float %Q<br>
+}<br>
+<br>
+; With sub reassociation, constant folding can eliminate the two 12 constants.<br>
+define float @test4(float %A, float %B, float %C, float %D) {<br>
+; CHECK-LABEL: test4<br>
+; CHECK-NEXT: %B.neg = fsub fast float -0.000000e+00, %B<br>
+; CHECK-NEXT: %O.neg = fsub fast float %B.neg, %A<br>
+; CHECK-NEXT: %P = fsub fast float %O.neg, %C<br>
+; CHECK-NEXT: %Q = fadd fast float %P, %D<br>
+; CHECK-NEXT: ret float %Q<br>
+<br>
+; FIXME: InstCombine should be able to get us to the following:<br>
+; %sum = fadd fast float %B, %A<br>
+; %sum1 = fadd fast float %sum, %C<br>
+; %Q = fsub fast float %D, %sum1<br>
+; ret i32 %Q<br>
+<br>
+  %M = fadd fast float 1.200000e+01, %A<br>
+  %N = fadd fast float %M, %B<br>
+  %O = fadd fast float %N, %C<br>
+  %P = fsub fast float %D, %O<br>
+  %Q = fadd fast float 1.200000e+01, %P<br>
+  ret float %Q<br>
+}<br>
<br>
Added: llvm/trunk/test/Transforms/<u></u>Reassociate/fast-basictest.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/fast-basictest.ll?rev=215647&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>Transforms/Reassociate/fast-<u></u>basictest.ll?rev=215647&view=<u></u>auto</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/Transforms/<u></u>Reassociate/fast-basictest.ll (added)<br>
+++ llvm/trunk/test/Transforms/<u></u>Reassociate/fast-basictest.ll Thu Aug 14 10:23:01 2014<br>
@@ -0,0 +1,285 @@<br>
+; RUN: opt < %s -reassociate -gvn -instcombine -S | FileCheck %s<br>
+<br>
+; With reassociation, constant folding can eliminate the 12 and -12 constants.<br>
+define float @test1(float %arg) {<br>
+; CHECK-LABEL: @test1<br>
+; CHECK-NEXT: fsub fast float -0.000000e+00, %arg<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %tmp1 = fsub fast float -1.200000e+01, %arg<br>
+  %tmp2 = fadd fast float %tmp1, 1.200000e+01<br>
+  ret float %tmp2<br>
+}<br>
+<br>
+define float @test2(float %reg109, float %reg1111) {<br>
+; CHECK-LABEL: @test2<br>
+; CHECK-NEXT: fadd float %reg109, -3.000000e+01<br>
+; CHECK-NEXT: fadd float %reg115, %reg1111<br>
+; CHECK-NEXT: fadd float %reg116, 3.000000e+01<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %reg115 = fadd float %reg109, -3.000000e+01<br>
+  %reg116 = fadd float %reg115, %reg1111<br>
+  %reg117 = fadd float %reg116, 3.000000e+01<br>
+  ret float %reg117<br>
+}<br>
+<br>
+define float @test3(float %reg109, float %reg1111) {<br>
+; CHECK-LABEL: @test3<br>
+; CHECK-NEXT: %reg117 = fadd fast float %reg109, %reg1111<br>
+; CHECK-NEXT:  ret float %reg117<br>
+<br>
+  %reg115 = fadd fast float %reg109, -3.000000e+01<br>
+  %reg116 = fadd fast float %reg115, %reg1111<br>
+  %reg117 = fadd fast float %reg116, 3.000000e+01<br>
+  ret float %reg117<br>
+}<br>
+<br>
+@fe = external global float<br>
+@fa = external global float<br>
+@fb = external global float<br>
+@fc = external global float<br>
+@ff = external global float<br>
+<br>
+define void @test4() {<br>
+; CHECK-LABEL: @test4<br>
+; CHECK: fadd fast float<br>
+; CHECK: fadd fast float<br>
+; CHECK-NOT: fadd fast float<br>
+; CHECK: ret void<br>
+<br>
+  %A = load float* @fa<br>
+  %B = load float* @fb<br>
+  %C = load float* @fc<br>
+  %t1 = fadd fast float %A, %B<br>
+  %t2 = fadd fast float %t1, %C<br>
+  %t3 = fadd fast float %C, %A<br>
+  %t4 = fadd fast float %t3, %B<br>
+  ; e = (a+b)+c;<br>
+  store float %t2, float* @fe<br>
+  ; f = (a+c)+b<br>
+  store float %t4, float* @ff<br>
+  ret void<br>
+}<br>
+<br>
+define void @test5() {<br>
+; CHECK-LABEL: @test5<br>
+; CHECK: fadd fast float<br>
+; CHECK: fadd fast float<br>
+; CHECK-NOT: fadd<br>
+; CHECK: ret void<br>
+<br>
+  %A = load float* @fa<br>
+  %B = load float* @fb<br>
+  %C = load float* @fc<br>
+  %t1 = fadd fast float %A, %B<br>
+  %t2 = fadd fast float %t1, %C<br>
+  %t3 = fadd fast float %C, %A<br>
+  %t4 = fadd fast float %t3, %B<br>
+  ; e = c+(a+b)<br>
+  store float %t2, float* @fe<br>
+  ; f = (c+a)+b<br>
+  store float %t4, float* @ff<br>
+  ret void<br>
+}<br>
+<br>
+define void @test6() {<br>
+; CHECK-LABEL: @test6<br>
+; CHECK: fadd fast float<br>
+; CHECK: fadd fast float<br>
+; CHECK-NOT: fadd<br>
+; CHECK: ret void<br>
+<br>
+  %A = load float* @fa<br>
+  %B = load float* @fb<br>
+  %C = load float* @fc<br>
+  %t1 = fadd fast float %B, %A<br>
+  %t2 = fadd fast float %t1, %C<br>
+  %t3 = fadd fast float %C, %A<br>
+  %t4 = fadd fast float %t3, %B<br>
+  ; e = c+(b+a)<br>
+  store float %t2, float* @fe<br>
+  ; f = (c+a)+b<br>
+  store float %t4, float* @ff<br>
+  ret void<br>
+}<br>
+<br>
+define float @test7(float %A, float %B, float %C) {<br>
+; CHECK-LABEL: @test7<br>
+; CHECK-NEXT: fadd fast float %C, %B<br>
+; CHECK-NEXT: fmul fast float %A, %A<br>
+; CHECK-NEXT: fmul fast float %1, %tmp2<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %aa = fmul fast float %A, %A<br>
+  %aab = fmul fast float %aa, %B<br>
+  %ac = fmul fast float %A, %C<br>
+  %aac = fmul fast float %ac, %A<br>
+  %r = fadd fast float %aab, %aac<br>
+  ret float %r<br>
+}<br>
+<br>
+define float @test8(float %X, float %Y, float %Z) {<br>
+; CHECK-LABEL: @test8<br>
+; CHECK-NEXT: fmul fast float %Y, %X<br>
+; CHECK-NEXT: fsub fast float %Z<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %A = fsub fast float 0.0, %X<br>
+  %B = fmul fast float %A, %Y<br>
+  ; (-X)*Y + Z -> Z-X*Y<br>
+  %C = fadd fast float %B, %Z<br>
+  ret float %C<br>
+}<br>
+<br>
+define float @test9(float %X) {<br>
+; CHECK-LABEL: @test9<br>
+; CHECK-NEXT: fmul fast float %X, 9.400000e+01<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %Y = fmul fast float %X, 4.700000e+01<br>
+  %Z = fadd fast float %Y, %Y<br>
+  ret float %Z<br>
+}<br>
+<br>
+define float @test10(float %X) {<br>
+; CHECK-LABEL: @test10<br>
+; CHECK-NEXT: fmul fast float %X, 3.000000e+00<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %Y = fadd fast float %X ,%X<br>
+  %Z = fadd fast float %Y, %X<br>
+  ret float %Z<br>
+}<br>
+<br>
+define float @test11(float %W) {<br>
+; CHECK-LABEL: test11<br>
+; CHECK-NEXT: fmul fast float %W, 3.810000e+02<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %X = fmul fast float %W, 127.0<br>
+  %Y = fadd fast float %X ,%X<br>
+  %Z = fadd fast float %Y, %X<br>
+  ret float %Z<br>
+}<br>
+<br>
+define float @test12(float %X) {<br>
+; CHECK-LABEL: @test12<br>
+; CHECK-NEXT: fmul fast float %X, -3.000000e+00<br>
+; CHECK-NEXT: fadd fast float %factor, 6.000000e+00<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %A = fsub fast float 1.000000e+00, %X<br>
+  %B = fsub fast float 2.000000e+00, %X<br>
+  %C = fsub fast float 3.000000e+00, %X<br>
+  %Y = fadd fast float %A ,%B<br>
+  %Z = fadd fast float %Y, %C<br>
+  ret float %Z<br>
+}<br>
+<br>
+define float @test13(float %X1, float %X2, float %X3) {<br>
+; CHECK-LABEL: @test13<br>
+; CHECK-NEXT: fsub fast float %X3, %X2<br>
+; CHECK-NEXT: fmul fast float {{.*}}, %X1<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %A = fsub fast float 0.000000e+00, %X1<br>
+  %B = fmul fast float %A, %X2   ; -X1*X2<br>
+  %C = fmul fast float %X1, %X3  ; X1*X3<br>
+  %D = fadd fast float %B, %C    ; -X1*X2 + X1*X3 -> X1*(X3-X2)<br>
+  ret float %D<br>
+}<br>
+<br>
+define float @test14(float %X1, float %X2) {<br>
+; CHECK-LABEL: @test14<br>
+; CHECK-NEXT: fsub fast float %X1, %X2<br>
+; CHECK-NEXT: fmul fast float %tmp, 4.700000e+01<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %B = fmul fast float %X1, 47.   ; X1*47<br>
+  %C = fmul fast float %X2, -47.  ; X2*-47<br>
+  %D = fadd fast float %B, %C    ; X1*47 + X2*-47 -> 47*(X1-X2)<br>
+  ret float %D<br>
+}<br>
+<br>
+define float @test15(float %arg) {<br>
+; CHECK-LABEL: test15<br>
+; CHECK-NEXT: fmul fast float %arg, 1.440000e+02<br>
+; CHECK-NEXT: ret float %tmp2<br>
+<br>
+  %tmp1 = fmul fast float 1.200000e+01, %arg<br>
+  %tmp2 = fmul fast float %tmp1, 1.200000e+01<br>
+  ret float %tmp2<br>
+}<br>
+<br>
+; (b+(a+1234))+-a -> b+1234<br>
+define float @test16(float %b, float %a) {<br>
+; CHECK-LABEL: @test16<br>
+; CHECK-NEXT: fadd fast float %b, 1.234000e+03<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %1 = fadd fast float %a, 1234.0<br>
+  %2 = fadd fast float %b, %1<br>
+  %3 = fsub fast float 0.0, %a<br>
+  %4 = fadd fast float %2, %3<br>
+  ret float %4<br>
+}<br>
+<br>
+; Test that we can turn things like X*-(Y*Z) -> X*-1*Y*Z.<br>
+<br>
+define float @test17(float %a, float %b, float %z) {<br>
+; CHECK-LABEL: test17<br>
+; CHECK-NEXT: fmul fast float %a, 1.234500e+04<br>
+; CHECK-NEXT: fmul fast float %e, %b<br>
+; CHECK-NEXT: fmul fast float %f, %z<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %c = fsub fast float 0.000000e+00, %z<br>
+  %d = fmul fast float %a, %b<br>
+  %e = fmul fast float %c, %d<br>
+  %f = fmul fast float %e, 1.234500e+04<br>
+  %g = fsub fast float 0.000000e+00, %f<br>
+  ret float %g<br>
+}<br>
+<br>
+define float @test18(float %a, float %b, float %z) {<br>
+; CHECK-LABEL: test18<br>
+; CHECK-NEXT: fmul fast float %a, 4.000000e+01<br>
+; CHECK-NEXT: fmul fast float %e, %z<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %d = fmul fast float %z, 4.000000e+01<br>
+  %c = fsub fast float 0.000000e+00, %d<br>
+  %e = fmul fast float %a, %c<br>
+  %f = fsub fast float 0.000000e+00, %e<br>
+  ret float %f<br>
+}<br>
+<br>
+; With sub reassociation, constant folding can eliminate the 12 and -12 constants.<br>
+define float @test19(float %A, float %B) {<br>
+; CHECK-LABEL: @test19<br>
+; CHECK-NEXT: fsub fast float %A, %B<br>
+; CHECK-NEXT: ret float<br>
+  %X = fadd fast float -1.200000e+01, %A<br>
+  %Y = fsub fast float %X, %B<br>
+  %Z = fadd fast float %Y, 1.200000e+01<br>
+  ret float %Z<br>
+}<br>
+<br>
+; With sub reassociation, constant folding can eliminate the uses of %a.<br>
+define float @test20(float %a, float %b, float %c) nounwind  {<br>
+; CHECK-LABEL: @test20<br>
+; CHECK-NEXT: fsub fast float -0.000000e+00, %b<br>
+; CHECK-NEXT: fsub fast float %b.neg, %c<br>
+; CHECK-NEXT: ret float<br>
+<br>
+; FIXME: Should be able to generate the below, which may expose more<br>
+;        opportunites for FAdd reassociation.<br>
+; %sum = fadd fast float %c, %b<br>
+; %tmp7 = fsub fast float 0, %sum<br>
+<br>
+  %tmp3 = fsub fast float %a, %b<br>
+  %tmp5 = fsub fast float %tmp3, %c<br>
+  %tmp7 = fsub fast float %tmp5, %a<br>
+  ret float %tmp7<br>
+}<br>
<br>
Added: llvm/trunk/test/Transforms/<u></u>Reassociate/fast-fp-commute.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/fast-fp-commute.ll?rev=215647&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>Transforms/Reassociate/fast-<u></u>fp-commute.ll?rev=215647&view=<u></u>auto</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/Transforms/<u></u>Reassociate/fast-fp-commute.ll (added)<br>
+++ llvm/trunk/test/Transforms/<u></u>Reassociate/fast-fp-commute.ll Thu Aug 14 10:23:01 2014<br>
@@ -0,0 +1,44 @@<br>
+; RUN: opt -reassociate -S < %s | FileCheck %s<br>
+<br>
+declare void @use(float)<br>
+<br>
+define void @test1(float %x, float %y) {<br>
+; CHECK-LABEL: test1<br>
+; CHECK: fmul fast float %y, %x<br>
+; CHECK: fmul fast float %y, %x<br>
+; CHECK: fsub fast float %1, %2<br>
+; CHECK: call void @use(float %{{.*}})<br>
+; CHECK: call void @use(float %{{.*}})<br>
+<br>
+  %1 = fmul fast float %x, %y<br>
+  %2 = fmul fast float %y, %x<br>
+  %3 = fsub fast float %1, %2<br>
+  call void @use(float %1)<br>
+  call void @use(float %3)<br>
+  ret void<br>
+}<br>
+<br>
+define float @test2(float %x, float %y) {<br>
+; CHECK-LABEL: test2<br>
+; CHECK-NEXT: fmul fast float %y, %x<br>
+; CHECK-NEXT: fmul fast float %y, %x<br>
+; CHECK-NEXT: fsub fast float %1, %2<br>
+; CHECK-NEXT: ret float %3<br>
+<br>
+  %1 = fmul fast float %x, %y<br>
+  %2 = fmul fast float %y, %x<br>
+  %3 = fsub fast float %1, %2<br>
+  ret float %3<br>
+}<br>
+<br>
+define float @test3(float %x, float %y) {<br>
+; CHECK-LABEL: test3<br>
+; CHECK-NEXT: %factor = fmul fast float 2.000000e+00, %y<br>
+; CHECK-NEXT: %tmp1 = fmul fast float %factor, %x<br>
+; CHECK-NEXT: ret float %tmp1<br>
+<br>
+  %1 = fmul fast float %x, %y<br>
+  %2 = fmul fast float %y, %x<br>
+  %3 = fadd fast float %1, %2<br>
+  ret float %3<br>
+}<br>
<br>
Added: llvm/trunk/test/Transforms/<u></u>Reassociate/fast-mightymul.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/fast-mightymul.ll?rev=215647&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>Transforms/Reassociate/fast-<u></u>mightymul.ll?rev=215647&view=<u></u>auto</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/Transforms/<u></u>Reassociate/fast-mightymul.ll (added)<br>
+++ llvm/trunk/test/Transforms/<u></u>Reassociate/fast-mightymul.ll Thu Aug 14 10:23:01 2014<br>
@@ -0,0 +1,35 @@<br>
+; RUN: opt < %s -reassociate -disable-output<br>
+; PR13021<br>
+<br>
+define float @test2(float %x) {<br>
+  %t0 = fmul fast float %x, %x<br>
+  %t1 = fmul fast float %t0, %t0<br>
+  %t2 = fmul fast float %t1, %t1<br>
+  %t3 = fmul fast float %t2, %t2<br>
+  %t4 = fmul fast float %t3, %t3<br>
+  %t5 = fmul fast float %t4, %t4<br>
+  %t6 = fmul fast float %t5, %t5<br>
+  %t7 = fmul fast float %t6, %t6<br>
+  %t8 = fmul fast float %t7, %t7<br>
+  %t9 = fmul fast float %t8, %t8<br>
+  %t10 = fmul fast float %t9, %t9<br>
+  %t11 = fmul fast float %t10, %t10<br>
+  %t12 = fmul fast float %t11, %t11<br>
+  %t13 = fmul fast float %t12, %t12<br>
+  %t14 = fmul fast float %t13, %t13<br>
+  %t15 = fmul fast float %t14, %t14<br>
+  %t16 = fmul fast float %t15, %t15<br>
+  %t17 = fmul fast float %t16, %t16<br>
+  %t18 = fmul fast float %t17, %t17<br>
+  %t19 = fmul fast float %t18, %t18<br>
+  %t20 = fmul fast float %t19, %t19<br>
+  %t21 = fmul fast float %t20, %t20<br>
+  %t22 = fmul fast float %t21, %t21<br>
+  %t23 = fmul fast float %t22, %t22<br>
+  %t24 = fmul fast float %t23, %t23<br>
+  %t25 = fmul fast float %t24, %t24<br>
+  %t26 = fmul fast float %t25, %t25<br>
+  %t27 = fmul fast float %t26, %t26<br>
+  %t28 = fmul fast float %t27, %t27<br>
+  ret float %t28<br>
+}<br>
<br>
Added: llvm/trunk/test/Transforms/<u></u>Reassociate/fast-multistep.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/fast-multistep.ll?rev=215647&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>Transforms/Reassociate/fast-<u></u>multistep.ll?rev=215647&view=<u></u>auto</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/Transforms/<u></u>Reassociate/fast-multistep.ll (added)<br>
+++ llvm/trunk/test/Transforms/<u></u>Reassociate/fast-multistep.ll Thu Aug 14 10:23:01 2014<br>
@@ -0,0 +1,32 @@<br>
+; RUN: opt < %s -reassociate -S | FileCheck %s<br>
+<br>
+define float @fmultistep1(float %a, float %b, float %c) {<br>
+; Check that a*a*b+a*a*c is turned into a*(a*(b+c)).<br>
+; CHECK-LABEL: @fmultistep1<br>
+; CHECK-NEXT: fadd fast float %c, %b<br>
+; CHECK-NEXT: fmul fast float %a, %tmp2<br>
+; CHECK-NEXT: fmul fast float %tmp3, %a<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %t0 = fmul fast float %a, %b<br>
+  %t1 = fmul fast float %a, %t0 ; a*(a*b)<br>
+  %t2 = fmul fast float %a, %c<br>
+  %t3 = fmul fast float %a, %t2 ; a*(a*c)<br>
+  %t4 = fadd fast float %t1, %t3<br>
+  ret float %t4<br>
+}<br>
+<br>
+define float @fmultistep2(float %a, float %b, float %c, float %d) {<br>
+; Check that a*b+a*c+d is turned into a*(b+c)+d.<br>
+; CHECK-LABEL: @fmultistep2<br>
+; CHECK-NEXT: fadd fast float %c, %b<br>
+; CHECK-NEXT: fmul fast float %tmp, %a<br>
+; CHECK-NEXT: fadd fast float %tmp1, %d<br>
+; CHECK-NEXT: ret float<br>
+<br>
+  %t0 = fmul fast float %a, %b<br>
+  %t1 = fmul fast float %a, %c<br>
+  %t2 = fadd fast float %t1, %d ; a*c+d<br>
+  %t3 = fadd fast float %t0, %t2 ; a*b+(a*c+d)<br>
+  ret float %t3<br>
+}<br>
<br>
<br>
______________________________<u></u>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/llvm-commits</a><br>
</blockquote>
<br>
<br>_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
<br></blockquote></div><br></div>