[llvm] r368512 - [Reassociate] try harder to convert negative FP constants to positive

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 10 06:17:54 PDT 2019


Author: spatel
Date: Sat Aug 10 06:17:54 2019
New Revision: 368512

URL: http://llvm.org/viewvc/llvm-project?rev=368512&view=rev
Log:
[Reassociate] try harder to convert negative FP constants to positive

This is an extension of a transform that tries to produce positive floating-point
constants to improve canonicalization (and hopefully lead to more reassociation
and CSE).

The original patches were:
D4904
D5363 (rL221721)

But as the test diffs show, these were limited to basic patterns by walking from
an instruction to its single user rather than recursively moving up the def-use
sequence. No fast-math is required here because we're only rearranging implicit
FP negations in intermediate ops.

A motivating bug is:
https://bugs.llvm.org/show_bug.cgi?id=32939

Differential Revision: https://reviews.llvm.org/D65954

Modified:
    llvm/trunk/include/llvm/Transforms/Scalar/Reassociate.h
    llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp
    llvm/trunk/test/Transforms/Reassociate/canonicalize-neg-const.ll
    llvm/trunk/test/Transforms/Reassociate/fast-ReassociateVector.ll
    llvm/trunk/test/Transforms/Reassociate/reassoc-intermediate-fnegs.ll

Modified: llvm/trunk/include/llvm/Transforms/Scalar/Reassociate.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar/Reassociate.h?rev=368512&r1=368511&r2=368512&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Scalar/Reassociate.h (original)
+++ llvm/trunk/include/llvm/Transforms/Scalar/Reassociate.h Sat Aug 10 06:17:54 2019
@@ -122,7 +122,9 @@ private:
   void EraseInst(Instruction *I);
   void RecursivelyEraseDeadInsts(Instruction *I, OrderedSet &Insts);
   void OptimizeInst(Instruction *I);
-  Instruction *canonicalizeNegConstExpr(Instruction *I);
+  Instruction *canonicalizeNegFPConstantsForOp(Instruction *I, Instruction *Op,
+                                               Value *OtherOp);
+  Instruction *canonicalizeNegFPConstants(Instruction *I);
   void BuildPairMap(ReversePostOrderTraversal<Function *> &RPOT);
 };
 

Modified: llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp?rev=368512&r1=368511&r2=368512&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp Sat Aug 10 06:17:54 2019
@@ -1938,88 +1938,132 @@ void ReassociatePass::EraseInst(Instruct
   MadeChange = true;
 }
 
-// Canonicalize expressions of the following form:
-//  x + (-Constant * y) -> x - (Constant * y)
-//  x - (-Constant * y) -> x + (Constant * y)
-Instruction *ReassociatePass::canonicalizeNegConstExpr(Instruction *I) {
-  if (!I->hasOneUse() || I->getType()->isVectorTy())
-    return nullptr;
-
-  // Must be a fmul or fdiv instruction.
-  unsigned Opcode = I->getOpcode();
-  if (Opcode != Instruction::FMul && Opcode != Instruction::FDiv)
-    return nullptr;
-
-  auto *C0 = dyn_cast<ConstantFP>(I->getOperand(0));
-  auto *C1 = dyn_cast<ConstantFP>(I->getOperand(1));
-
-  // Both operands are constant, let it get constant folded away.
-  if (C0 && C1)
-    return nullptr;
-
-  ConstantFP *CF = C0 ? C0 : C1;
-
-  // Must have one constant operand.
-  if (!CF)
-    return nullptr;
-
-  // Must be a negative ConstantFP.
-  if (!CF->isNegative())
-    return nullptr;
-
-  // User must be a binary operator with one or more uses.
-  Instruction *User = I->user_back();
-  if (!isa<BinaryOperator>(User) || User->use_empty())
-    return nullptr;
+/// Recursively analyze an expression to build a list of instructions that have
+/// negative floating-point constant operands. The caller can then transform
+/// the list to create positive constants for better reassociation and CSE.
+static void getNegatibleInsts(Value *V,
+                              SmallVectorImpl<Instruction *> &Candidates) {
+  // Handle only one-use instructions. Combining negations does not justify
+  // replicating instructions.
+  Instruction *I;
+  if (!match(V, m_OneUse(m_Instruction(I))))
+    return;
 
-  unsigned UserOpcode = User->getOpcode();
-  if (UserOpcode != Instruction::FAdd && UserOpcode != Instruction::FSub)
-    return nullptr;
+  // Handle expressions of multiplications and divisions.
+  // TODO: This could look through floating-point casts.
+  const APFloat *C;
+  switch (I->getOpcode()) {
+    case Instruction::FMul:
+      // Not expecting non-canonical code here. Bail out and wait.
+      if (match(I->getOperand(0), m_Constant()))
+        break;
+
+      if (match(I->getOperand(1), m_APFloat(C)) && C->isNegative()) {
+        Candidates.push_back(I);
+        LLVM_DEBUG(dbgs() << "FMul with negative constant: " << *I << '\n');
+      }
+      getNegatibleInsts(I->getOperand(0), Candidates);
+      getNegatibleInsts(I->getOperand(1), Candidates);
+      break;
+    case Instruction::FDiv:
+      // Not expecting non-canonical code here. Bail out and wait.
+      if (match(I->getOperand(0), m_Constant()) &&
+          match(I->getOperand(1), m_Constant()))
+        break;
+
+      if ((match(I->getOperand(0), m_APFloat(C)) && C->isNegative()) ||
+          (match(I->getOperand(1), m_APFloat(C)) && C->isNegative())) {
+        Candidates.push_back(I);
+        LLVM_DEBUG(dbgs() << "FDiv with negative constant: " << *I << '\n');
+      }
+      getNegatibleInsts(I->getOperand(0), Candidates);
+      getNegatibleInsts(I->getOperand(1), Candidates);
+      break;
+    default:
+      break;
+  }
+}
 
-  // Subtraction is not commutative. Explicitly, the following transform is
-  // not valid: (-Constant * y) - x  -> x + (Constant * y)
-  if (!User->isCommutative() && User->getOperand(1) != I)
+/// Given an fadd/fsub with an operand that is a one-use instruction
+/// (the fadd/fsub), try to change negative floating-point constants into
+/// positive constants to increase potential for reassociation and CSE.
+Instruction *ReassociatePass::canonicalizeNegFPConstantsForOp(Instruction *I,
+                                                              Instruction *Op,
+                                                              Value *OtherOp) {
+  assert((I->getOpcode() == Instruction::FAdd ||
+          I->getOpcode() == Instruction::FSub) && "Expected fadd/fsub");
+
+  // Collect instructions with negative FP constants from the subtree that ends
+  // in Op.
+  SmallVector<Instruction *, 4> Candidates;
+  getNegatibleInsts(Op, Candidates);
+  if (Candidates.empty())
     return nullptr;
 
   // Don't canonicalize x + (-Constant * y) -> x - (Constant * y), if the
   // resulting subtract will be broken up later.  This can get us into an
   // infinite loop during reassociation.
-  if (UserOpcode == Instruction::FAdd && ShouldBreakUpSubtract(User))
+  bool IsFSub = I->getOpcode() == Instruction::FSub;
+  bool NeedsSubtract = !IsFSub && Candidates.size() % 2 == 1;
+  if (NeedsSubtract && ShouldBreakUpSubtract(I))
     return nullptr;
 
-  // Change the sign of the constant.
-  APFloat Val = CF->getValueAPF();
-  Val.changeSign();
-  I->setOperand(C0 ? 0 : 1, ConstantFP::get(CF->getContext(), Val));
-
-  // Canonicalize I to RHS to simplify the next bit of logic. E.g.,
-  // ((-Const*y) + x) -> (x + (-Const*y)).
-  if (User->getOperand(0) == I && User->isCommutative())
-    cast<BinaryOperator>(User)->swapOperands();
-
-  Value *Op0 = User->getOperand(0);
-  Value *Op1 = User->getOperand(1);
-  BinaryOperator *NI;
-  switch (UserOpcode) {
-  default:
-    llvm_unreachable("Unexpected Opcode!");
-  case Instruction::FAdd:
-    NI = BinaryOperator::CreateFSub(Op0, Op1);
-    NI->setFastMathFlags(cast<FPMathOperator>(User)->getFastMathFlags());
-    break;
-  case Instruction::FSub:
-    NI = BinaryOperator::CreateFAdd(Op0, Op1);
-    NI->setFastMathFlags(cast<FPMathOperator>(User)->getFastMathFlags());
-    break;
+  for (Instruction *Negatible : Candidates) {
+    const APFloat *C;
+    if (match(Negatible->getOperand(0), m_APFloat(C))) {
+      assert(!match(Negatible->getOperand(1), m_Constant()) &&
+             "Expecting only 1 constant operand");
+      assert(C->isNegative() && "Expected negative FP constant");
+      Negatible->setOperand(0, ConstantFP::get(Negatible->getType(), abs(*C)));
+      MadeChange = true;
+    }
+    if (match(Negatible->getOperand(1), m_APFloat(C))) {
+      assert(!match(Negatible->getOperand(0), m_Constant()) &&
+             "Expecting only 1 constant operand");
+      assert(C->isNegative() && "Expected negative FP constant");
+      Negatible->setOperand(1, ConstantFP::get(Negatible->getType(), abs(*C)));
+      MadeChange = true;
+    }
   }
+  assert(MadeChange == true && "Negative constant candidate was not changed");
 
-  NI->insertBefore(User);
-  NI->setName(User->getName());
-  User->replaceAllUsesWith(NI);
-  NI->setDebugLoc(I->getDebugLoc());
+  // Negations cancelled out.
+  if (Candidates.size() % 2 == 0)
+    return I;
+
+  // Negate the final operand in the expression by flipping the opcode of this
+  // fadd/fsub.
+  assert(Candidates.size() % 2 == 1 && "Expected odd number");
+  IRBuilder<> Builder(I);
+  Value *NewInst = IsFSub ? Builder.CreateFAddFMF(OtherOp, Op, I)
+                          : Builder.CreateFSubFMF(OtherOp, Op, I);
+  I->replaceAllUsesWith(NewInst);
   RedoInsts.insert(I);
-  MadeChange = true;
-  return NI;
+  return dyn_cast<Instruction>(NewInst);
+}
+
+/// Canonicalize expressions that contain a negative floating-point constant
+/// of the following form:
+///   OtherOp + (subtree) -> OtherOp {+/-} (canonical subtree)
+///   (subtree) + OtherOp -> OtherOp {+/-} (canonical subtree)
+///   OtherOp - (subtree) -> OtherOp {+/-} (canonical subtree)
+///
+/// The fadd/fsub opcode may be switched to allow folding a negation into the
+/// input instruction.
+Instruction *ReassociatePass::canonicalizeNegFPConstants(Instruction *I) {
+  LLVM_DEBUG(dbgs() << "Combine negations for: " << *I << '\n');
+  Value *X;
+  Instruction *Op;
+  if (match(I, m_FAdd(m_Value(X), m_OneUse(m_Instruction(Op)))))
+    if (Instruction *R = canonicalizeNegFPConstantsForOp(I, Op, X))
+      I = R;
+  if (match(I, m_FAdd(m_OneUse(m_Instruction(Op)), m_Value(X))))
+    if (Instruction *R = canonicalizeNegFPConstantsForOp(I, Op, X))
+      I = R;
+  if (match(I, m_FSub(m_Value(X), m_OneUse(m_Instruction(Op)))))
+    if (Instruction *R = canonicalizeNegFPConstantsForOp(I, Op, X))
+      I = R;
+  return I;
 }
 
 /// Inspect and optimize the given instruction. Note that erasing
@@ -2042,16 +2086,16 @@ void ReassociatePass::OptimizeInst(Instr
       I = NI;
     }
 
-  // Canonicalize negative constants out of expressions.
-  if (Instruction *Res = canonicalizeNegConstExpr(I))
-    I = Res;
-
   // Commute binary operators, to canonicalize the order of their operands.
   // This can potentially expose more CSE opportunities, and makes writing other
   // transformations simpler.
   if (I->isCommutative())
     canonicalizeOperands(I);
 
+  // Canonicalize negative constants out of expressions.
+  if (Instruction *Res = canonicalizeNegFPConstants(I))
+    I = Res;
+
   // Don't optimize floating-point instructions unless they are 'fast'.
   if (I->getType()->isFPOrFPVectorTy() && !I->isFast())
     return;

Modified: llvm/trunk/test/Transforms/Reassociate/canonicalize-neg-const.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/canonicalize-neg-const.ll?rev=368512&r1=368511&r2=368512&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Reassociate/canonicalize-neg-const.ll (original)
+++ llvm/trunk/test/Transforms/Reassociate/canonicalize-neg-const.ll Sat Aug 10 06:17:54 2019
@@ -187,10 +187,10 @@ define double @pr34078(double %A) {
 
 define double @fadd_fmul_neg_const1(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fadd_fmul_neg_const1(
-; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[B:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[MUL1:%.*]] = fmul double [[MUL0]], [[C:%.*]]
-; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[A:%.*]], [[MUL1]]
-; CHECK-NEXT:    ret double [[ADD]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fsub double [[A:%.*]], [[MUL1]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %mul0 = fmul double %b, -3.0
   %mul1 = fmul double %mul0, %c
@@ -200,11 +200,11 @@ define double @fadd_fmul_neg_const1(doub
 
 define double @fadd_fmul_neg_const2(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fadd_fmul_neg_const2(
-; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
 ; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
-; CHECK-NEXT:    [[ADD1:%.*]] = fsub double [[A]], [[MUL2]]
-; CHECK-NEXT:    ret double [[ADD1]]
+; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[A]], [[MUL2]]
+; CHECK-NEXT:    ret double [[ADD]]
 ;
   %mul0 = fmul double %a, -3.0
   %mul1 = fmul double %mul0, %b
@@ -215,12 +215,12 @@ define double @fadd_fmul_neg_const2(doub
 
 define double @fadd_fmul_neg_const3(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fadd_fmul_neg_const3(
-; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
-; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[MUL1]], -4.000000e+00
+; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
 ; CHECK-NEXT:    [[MUL3:%.*]] = fmul double [[MUL2]], 5.000000e+00
-; CHECK-NEXT:    [[ADD1:%.*]] = fsub double [[C:%.*]], [[MUL3]]
-; CHECK-NEXT:    ret double [[ADD1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fsub double [[C:%.*]], [[MUL3]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %mul0 = fmul double %a, -3.0
   %mul1 = fmul double %mul0, %b
@@ -232,10 +232,10 @@ define double @fadd_fmul_neg_const3(doub
 
 define double @fsub_fmul_neg_const1(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fsub_fmul_neg_const1(
-; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[B:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[MUL1:%.*]] = fmul double [[MUL0]], [[C:%.*]]
-; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[A:%.*]], [[MUL1]]
-; CHECK-NEXT:    ret double [[SUB]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd double [[A:%.*]], [[MUL1]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %mul0 = fmul double %b, -3.0
   %mul1 = fmul double %mul0, %c
@@ -245,11 +245,11 @@ define double @fsub_fmul_neg_const1(doub
 
 define double @fsub_fmul_neg_const2(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fsub_fmul_neg_const2(
-; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
 ; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
-; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[A]], [[MUL2]]
-; CHECK-NEXT:    ret double [[SUB]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd double [[A]], [[MUL2]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %mul0 = fmul double %a, -3.0
   %mul1 = fmul double %mul0, %b
@@ -262,10 +262,10 @@ define double @fsub_fmul_neg_const3(doub
 ; CHECK-LABEL: @fsub_fmul_neg_const3(
 ; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[MUL1:%.*]] = fmul double [[MUL0]], [[B:%.*]]
-; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[MUL1]], -4.000000e+00
+; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[MUL1]], 4.000000e+00
 ; CHECK-NEXT:    [[MUL3:%.*]] = fmul double [[MUL2]], 5.000000e+00
-; CHECK-NEXT:    [[SUB1:%.*]] = fadd double [[C:%.*]], [[MUL3]]
-; CHECK-NEXT:    ret double [[SUB1]]
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[C:%.*]], [[MUL3]]
+; CHECK-NEXT:    ret double [[SUB]]
 ;
   %mul0 = fmul double %a, 3.0
   %mul1 = fmul double %mul0, %b
@@ -277,10 +277,10 @@ define double @fsub_fmul_neg_const3(doub
 
 define double @fadd_fdiv_neg_const1(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fadd_fdiv_neg_const1(
-; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double [[B:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[DIV0]], [[C:%.*]]
-; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[A:%.*]], [[DIV1]]
-; CHECK-NEXT:    ret double [[ADD]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fsub double [[A:%.*]], [[DIV1]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %div0 = fdiv double %b, -3.0
   %div1 = fdiv double %div0, %c
@@ -290,11 +290,11 @@ define double @fadd_fdiv_neg_const1(doub
 
 define double @fadd_fdiv_neg_const2(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fadd_fdiv_neg_const2(
-; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
 ; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
 ; CHECK-NEXT:    [[DIV2:%.*]] = fdiv double [[DIV1]], 7.000000e+00
-; CHECK-NEXT:    [[ADD1:%.*]] = fsub double [[A]], [[DIV2]]
-; CHECK-NEXT:    ret double [[ADD1]]
+; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[A]], [[DIV2]]
+; CHECK-NEXT:    ret double [[ADD]]
 ;
   %div0 = fdiv double -3.0, %a
   %div1 = fdiv double %div0, %b
@@ -305,9 +305,9 @@ define double @fadd_fdiv_neg_const2(doub
 
 define double @fadd_fdiv_neg_const3(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fadd_fdiv_neg_const3(
-; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double [[A:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
-; CHECK-NEXT:    [[DIV2:%.*]] = fdiv double -4.000000e+00, [[DIV1]]
+; CHECK-NEXT:    [[DIV2:%.*]] = fdiv double 4.000000e+00, [[DIV1]]
 ; CHECK-NEXT:    [[DIV3:%.*]] = fdiv double [[DIV2]], 5.000000e+00
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[C:%.*]], [[DIV3]]
 ; CHECK-NEXT:    ret double [[ADD]]
@@ -322,10 +322,10 @@ define double @fadd_fdiv_neg_const3(doub
 
 define double @fsub_fdiv_neg_const1(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fsub_fdiv_neg_const1(
-; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double [[B:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[DIV0]], [[C:%.*]]
-; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[A:%.*]], [[DIV1]]
-; CHECK-NEXT:    ret double [[SUB]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd double [[A:%.*]], [[DIV1]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %div0 = fdiv double %b, -3.0
   %div1 = fdiv double %div0, %c
@@ -335,11 +335,11 @@ define double @fsub_fdiv_neg_const1(doub
 
 define double @fsub_fdiv_neg_const2(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fsub_fdiv_neg_const2(
-; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
 ; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
 ; CHECK-NEXT:    [[DIV2:%.*]] = fdiv double [[DIV1]], 7.000000e+00
-; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[A]], [[DIV2]]
-; CHECK-NEXT:    ret double [[SUB]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd double [[A]], [[DIV2]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %div0 = fdiv double -3.0, %a
   %div1 = fdiv double %div0, %b
@@ -350,12 +350,12 @@ define double @fsub_fdiv_neg_const2(doub
 
 define double @fsub_fdiv_neg_const3(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fsub_fdiv_neg_const3(
-; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
 ; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[DIV0]], [[B:%.*]]
-; CHECK-NEXT:    [[DIV2:%.*]] = fdiv double [[DIV1]], -7.000000e+00
+; CHECK-NEXT:    [[DIV2:%.*]] = fdiv double [[DIV1]], 7.000000e+00
 ; CHECK-NEXT:    [[DIV3:%.*]] = fdiv double 5.000000e+00, [[DIV2]]
-; CHECK-NEXT:    [[SUB1:%.*]] = fadd double [[C:%.*]], [[DIV3]]
-; CHECK-NEXT:    ret double [[SUB1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd double [[C:%.*]], [[DIV3]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %div0 = fdiv double -3.0, %a
   %div1 = fdiv double %div0, %b
@@ -367,10 +367,10 @@ define double @fsub_fdiv_neg_const3(doub
 
 define double @fadd_mix_neg_const1(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fadd_mix_neg_const1(
-; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[B:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[MUL0]], [[C:%.*]]
-; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[A:%.*]], [[DIV1]]
-; CHECK-NEXT:    ret double [[ADD]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fsub double [[A:%.*]], [[DIV1]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %mul0 = fmul double %b, -3.0
   %div1 = fdiv double %mul0, %c
@@ -380,11 +380,11 @@ define double @fadd_mix_neg_const1(doubl
 
 define double @fadd_mix_neg_const2(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fadd_mix_neg_const2(
-; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
 ; CHECK-NEXT:    [[MUL1:%.*]] = fmul double [[DIV0]], [[B:%.*]]
 ; CHECK-NEXT:    [[DIV2:%.*]] = fdiv double [[MUL1]], 5.000000e+00
-; CHECK-NEXT:    [[ADD1:%.*]] = fsub double [[A]], [[DIV2]]
-; CHECK-NEXT:    ret double [[ADD1]]
+; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[A]], [[DIV2]]
+; CHECK-NEXT:    ret double [[ADD]]
 ;
   %div0 = fdiv double -3.0, %a
   %mul1 = fmul double %div0, %b
@@ -395,12 +395,12 @@ define double @fadd_mix_neg_const2(doubl
 
 define double @fadd_mix_neg_const3(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fadd_mix_neg_const3(
-; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[MUL0]], [[B:%.*]]
-; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[DIV1]], -4.000000e+00
+; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[DIV1]], 4.000000e+00
 ; CHECK-NEXT:    [[DIV3:%.*]] = fdiv double [[MUL2]], 5.000000e+00
-; CHECK-NEXT:    [[ADD1:%.*]] = fsub double [[C:%.*]], [[DIV3]]
-; CHECK-NEXT:    ret double [[ADD1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fsub double [[C:%.*]], [[DIV3]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %mul0 = fmul double %a, -3.0
   %div1 = fdiv double %mul0, %b
@@ -412,10 +412,10 @@ define double @fadd_mix_neg_const3(doubl
 
 define double @fsub_mix_neg_const1(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fsub_mix_neg_const1(
-; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double [[B:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double [[B:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[MUL1:%.*]] = fmul double [[DIV0]], [[C:%.*]]
-; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[A:%.*]], [[MUL1]]
-; CHECK-NEXT:    ret double [[SUB]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd double [[A:%.*]], [[MUL1]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %div0 = fdiv double %b, -3.0
   %mul1 = fmul double %div0, %c
@@ -424,11 +424,11 @@ define double @fsub_mix_neg_const1(doubl
 }
 define double @fsub_mix_neg_const2(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fsub_mix_neg_const2(
-; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
+; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], 3.000000e+00
 ; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[MUL0]], [[B:%.*]]
 ; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[DIV1]], 5.000000e+00
-; CHECK-NEXT:    [[SUB1:%.*]] = fadd double [[A]], [[MUL2]]
-; CHECK-NEXT:    ret double [[SUB1]]
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[A]], [[MUL2]]
+; CHECK-NEXT:    ret double [[SUB]]
 ;
   %mul0 = fmul double -3.0, %a
   %div1 = fdiv double %mul0, %b
@@ -439,12 +439,12 @@ define double @fsub_mix_neg_const2(doubl
 
 define double @fsub_mix_neg_const3(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fsub_mix_neg_const3(
-; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
 ; CHECK-NEXT:    [[MUL1:%.*]] = fmul double [[DIV0]], [[B:%.*]]
-; CHECK-NEXT:    [[DIV2:%.*]] = fdiv double [[MUL1]], -7.000000e+00
+; CHECK-NEXT:    [[DIV2:%.*]] = fdiv double [[MUL1]], 7.000000e+00
 ; CHECK-NEXT:    [[MUL3:%.*]] = fmul double [[DIV2]], 5.000000e+00
-; CHECK-NEXT:    [[SUB1:%.*]] = fadd double [[C:%.*]], [[MUL3]]
-; CHECK-NEXT:    ret double [[SUB1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd double [[C:%.*]], [[MUL3]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %div0 = fdiv double -3.0, %a
   %mul1 = fmul double %div0, %b
@@ -458,10 +458,10 @@ define double @fadd_both_ops_mix_neg_con
 ; CHECK-LABEL: @fadd_both_ops_mix_neg_const1(
 ; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[B:%.*]], -3.000000e+00
 ; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[MUL0]], [[C:%.*]]
-; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[A:%.*]], -4.000000e+00
+; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[A:%.*]], 4.000000e+00
 ; CHECK-NEXT:    [[DIV3:%.*]] = fdiv double [[MUL2]], [[C]]
-; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[DIV1]], [[DIV3]]
-; CHECK-NEXT:    ret double [[ADD]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fsub double [[DIV1]], [[DIV3]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %mul0 = fmul double %b, -3.0
   %div1 = fdiv double %mul0, %c
@@ -473,14 +473,14 @@ define double @fadd_both_ops_mix_neg_con
 
 define double @fadd_both_ops_mix_neg_const2(double %a, double %b, double %c) {
 ; CHECK-LABEL: @fadd_both_ops_mix_neg_const2(
-; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double -3.000000e+00, [[A:%.*]]
+; CHECK-NEXT:    [[DIV0:%.*]] = fdiv double 3.000000e+00, [[A:%.*]]
 ; CHECK-NEXT:    [[MUL1:%.*]] = fmul double [[DIV0]], [[B:%.*]]
 ; CHECK-NEXT:    [[DIV2:%.*]] = fdiv double [[MUL1]], 7.000000e+00
-; CHECK-NEXT:    [[DIV3:%.*]] = fdiv double -5.000000e+00, [[C:%.*]]
+; CHECK-NEXT:    [[DIV3:%.*]] = fdiv double 5.000000e+00, [[C:%.*]]
 ; CHECK-NEXT:    [[MUL4:%.*]] = fmul double [[B]], [[DIV3]]
-; CHECK-NEXT:    [[DIV5:%.*]] = fdiv double [[MUL4]], -6.000000e+00
-; CHECK-NEXT:    [[ADD1:%.*]] = fsub double [[DIV5]], [[DIV2]]
-; CHECK-NEXT:    ret double [[ADD1]]
+; CHECK-NEXT:    [[DIV5:%.*]] = fdiv double [[MUL4]], 6.000000e+00
+; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[DIV2]], [[DIV5]]
+; CHECK-NEXT:    ret double [[ADD]]
 ;
   %div0 = fdiv double -3.0, %a
   %mul1 = fmul double %div0, %b
@@ -497,13 +497,13 @@ define double @fadd_both_opsmix_neg_cons
 ; CHECK-NEXT:    [[MUL0:%.*]] = fmul double [[A:%.*]], -3.000000e+00
 ; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[MUL0]], [[B:%.*]]
 ; CHECK-NEXT:    [[MUL2:%.*]] = fmul double [[DIV1]], -4.000000e+00
-; CHECK-NEXT:    [[DIV3:%.*]] = fdiv double [[MUL2]], 5.000000e+00
-; CHECK-NEXT:    [[MUL4:%.*]] = fmul double [[C:%.*]], -6.000000e+00
+; CHECK-NEXT:    [[DIV3:%.*]] = fdiv double [[MUL2]], -5.000000e+00
+; CHECK-NEXT:    [[MUL4:%.*]] = fmul double [[C:%.*]], 6.000000e+00
 ; CHECK-NEXT:    [[DIV5:%.*]] = fdiv double [[MUL4]], [[B]]
-; CHECK-NEXT:    [[MUL6:%.*]] = fmul double [[DIV5]], -7.000000e+00
-; CHECK-NEXT:    [[MUL7:%.*]] = fdiv double [[MUL6]], -9.000000e+00
-; CHECK-NEXT:    [[ADD1:%.*]] = fsub double [[MUL7]], [[DIV3]]
-; CHECK-NEXT:    ret double [[ADD1]]
+; CHECK-NEXT:    [[MUL6:%.*]] = fmul double [[DIV5]], 7.000000e+00
+; CHECK-NEXT:    [[MUL7:%.*]] = fdiv double [[MUL6]], 9.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = fsub double [[DIV3]], [[MUL7]]
+; CHECK-NEXT:    ret double [[TMP1]]
 ;
   %mul0 = fmul double %a, -3.0
   %div1 = fdiv double %mul0, %b

Modified: llvm/trunk/test/Transforms/Reassociate/fast-ReassociateVector.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/fast-ReassociateVector.ll?rev=368512&r1=368511&r2=368512&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Reassociate/fast-ReassociateVector.ll (original)
+++ llvm/trunk/test/Transforms/Reassociate/fast-ReassociateVector.ll Sat Aug 10 06:17:54 2019
@@ -282,9 +282,10 @@ define <2 x double> @test9_reassoc_unary
 define <2 x float> @test10(<2 x float> %a, <2 x float> %b, <2 x float> %z) {
 ; CHECK-LABEL: @test10(
 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast <2 x float> zeroinitializer, zeroinitializer
-; CHECK-NEXT:    [[E:%.*]] = fmul fast <2 x float> [[A:%.*]], <float 4.000000e+01, float 4.000000e+01>
-; CHECK-NEXT:    [[F:%.*]] = fmul fast <2 x float> [[E]], [[Z:%.*]]
-; CHECK-NEXT:    ret <2 x float> [[F]]
+; CHECK-NEXT:    [[C:%.*]] = fmul fast <2 x float> [[A:%.*]], <float 4.000000e+01, float 4.000000e+01>
+; CHECK-NEXT:    [[E:%.*]] = fmul fast <2 x float> [[C]], [[Z:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = fadd fast <2 x float> [[E]], zeroinitializer
+; CHECK-NEXT:    ret <2 x float> [[TMP2]]
 ;
   %d = fmul fast <2 x float> %z, <float 4.000000e+01, float 4.000000e+01>
   %c = fsub fast <2 x float> <float 0.000000e+00, float 0.000000e+00>, %d
@@ -343,7 +344,7 @@ define <2 x float> @test10_reassoc_unary
 
 define <2 x double> @test11(<2 x double> %x, <2 x double> %y) {
 ; CHECK-LABEL: @test11(
-; CHECK-NEXT:    [[FACTOR:%.*]] = fmul fast <2 x double> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[FACTOR:%.*]] = fmul fast <2 x double> [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[REASS_MUL:%.*]] = fmul fast <2 x double> [[FACTOR]], <double 2.000000e+00, double 2.000000e+00>
 ; CHECK-NEXT:    ret <2 x double> [[REASS_MUL]]
 ;
@@ -381,15 +382,13 @@ define <2 x i64> @test12(<2 x i64> %b, <
   ret <2 x i64> %shl
 }
 
-; FIXME: expressions with a negative const should be canonicalized to assist
-; further reassociation.
-; We would expect (-5*b)+a -> a-(5*b) but only the constant operand is commuted.
+; (-5*b)+a -> a-(5*b)
 
 define <4 x float> @test13(<4 x float> %a, <4 x float> %b) {
 ; CHECK-LABEL: @test13(
-; CHECK-NEXT:    [[MUL:%.*]] = fmul fast <4 x float> [[B:%.*]], <float -5.000000e+00, float -5.000000e+00, float -5.000000e+00, float -5.000000e+00>
-; CHECK-NEXT:    [[ADD:%.*]] = fadd fast <4 x float> [[MUL]], [[A:%.*]]
-; CHECK-NEXT:    ret <4 x float> [[ADD]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast <4 x float> [[B:%.*]], <float 5.000000e+00, float 5.000000e+00, float 5.000000e+00, float 5.000000e+00>
+; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast <4 x float> [[A:%.*]], [[MUL]]
+; CHECK-NEXT:    ret <4 x float> [[TMP1]]
 ;
   %mul = fmul fast <4 x float> <float -5.000000e+00, float -5.000000e+00, float -5.000000e+00, float -5.000000e+00>, %b
   %add = fadd fast <4 x float> %mul, %a

Modified: llvm/trunk/test/Transforms/Reassociate/reassoc-intermediate-fnegs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/reassoc-intermediate-fnegs.ll?rev=368512&r1=368511&r2=368512&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Reassociate/reassoc-intermediate-fnegs.ll (original)
+++ llvm/trunk/test/Transforms/Reassociate/reassoc-intermediate-fnegs.ll Sat Aug 10 06:17:54 2019
@@ -1,15 +1,15 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt < %s -reassociate -S | FileCheck %s
 
-; Input is A op (B op C)
+; B * 5 + A * -5
+; TODO: (B - A) * 5
 
 define half @faddsubAssoc1(half %a, half %b) {
 ; CHECK-LABEL: @faddsubAssoc1(
-; CHECK-NEXT:    [[T2_NEG:%.*]] = fmul fast half [[A:%.*]], 0xH4500
+; CHECK-NEXT:    [[T2_NEG:%.*]] = fmul fast half [[A:%.*]], 0xHC500
 ; CHECK-NEXT:    [[REASS_MUL:%.*]] = fmul fast half [[B:%.*]], 0xH4500
-; CHECK-NEXT:    [[T51:%.*]] = fsub fast half [[REASS_MUL]], [[T2_NEG]]
 ; CHECK-NEXT:    [[T5:%.*]] = fadd fast half [[REASS_MUL]], [[T2_NEG]]
-; CHECK-NEXT:    ret half [[T51]]
+; CHECK-NEXT:    ret half [[T5]]
 ;
   %t1 = fmul fast half %b, 0xH4200 ; 3*b
   %t2 = fmul fast half %a, 0xH4500 ; 5*a
@@ -19,7 +19,7 @@ define half @faddsubAssoc1(half %a, half
   ret half %t5 ; = 5 * (b - a)
 }
 
-; Input is (A op B) op C
+; B + A * 5
 
 define half @faddsubAssoc2(half %a, half %b) {
 ; CHECK-LABEL: @faddsubAssoc2(




More information about the llvm-commits mailing list