Index: llvm/lib/Transforms/Scalar/Reassociate.cpp =================================================================== --- llvm/lib/Transforms/Scalar/Reassociate.cpp +++ llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -266,12 +266,20 @@ /// Replace 0-X with X*-1. static BinaryOperator *LowerNegateToMultiply(Instruction *Neg) { + assert((isa(Neg) || isa(Neg)) && + "Expected a Negate!"); + // It's not safe to lower a unary FNeg into a FMul by -1.0. However, + // we can only reach this function with fast flags set, so it's + // safe to do with nnan and nsz. + assert((!isa(Neg) || Neg->isFast()) && + "Expecting FastMathFlags!"); + unsigned OpNo = isa(Neg) ? 1 : 0; Type *Ty = Neg->getType(); Constant *NegOne = Ty->isIntOrIntVectorTy() ? ConstantInt::getAllOnesValue(Ty) : ConstantFP::get(Ty, -1.0); - BinaryOperator *Res = CreateMul(Neg->getOperand(1), NegOne, "", Neg, Neg); - Neg->setOperand(1, Constant::getNullValue(Ty)); // Drop use of op. + BinaryOperator *Res = CreateMul(Neg->getOperand(OpNo), NegOne, "", Neg, Neg); + Neg->setOperand(OpNo, Constant::getNullValue(Ty)); // Drop use of op. Res->takeName(Neg); Neg->replaceAllUsesWith(Res); Res->setDebugLoc(Neg->getDebugLoc()); @@ -444,8 +452,10 @@ /// that have all uses inside the expression (i.e. only used by non-leaf nodes /// of the expression) if it can turn them into binary operators of the right /// type and thus make the expression bigger. -static bool LinearizeExprTree(BinaryOperator *I, +static bool LinearizeExprTree(Instruction *I, SmallVectorImpl &Ops) { + assert((isa(I) || isa(I)) && + "Expected a UnaryOperator or BinaryOperator!"); LLVM_DEBUG(dbgs() << "LINEARIZE: " << *I << '\n'); unsigned Bitwidth = I->getType()->getScalarType()->getPrimitiveSizeInBits(); unsigned Opcode = I->getOpcode(); @@ -462,7 +472,7 @@ // with their weights, representing a certain number of paths to the operator. // If an operator occurs in the worklist multiple times then we found multiple // ways to get to it. - SmallVector, 8> Worklist; // (Op, Weight) + SmallVector, 8> Worklist; // (Op, Weight) Worklist.push_back(std::make_pair(I, APInt(Bitwidth, 1))); bool Changed = false; @@ -489,10 +499,10 @@ SmallPtrSet Visited; // For sanity checking the iteration scheme. #endif while (!Worklist.empty()) { - std::pair P = Worklist.pop_back_val(); + std::pair P = Worklist.pop_back_val(); I = P.first; // We examine the operands of this binary operator. - for (unsigned OpIdx = 0; OpIdx < 2; ++OpIdx) { // Visit operands. + for (unsigned OpIdx = 0; OpIdx < I->getNumOperands(); ++OpIdx) { // Visit operands. Value *Op = I->getOperand(OpIdx); APInt Weight = P.second; // Number of paths to this operand. LLVM_DEBUG(dbgs() << "OPERAND: " << *Op << " (" << Weight << ")\n"); @@ -500,7 +510,7 @@ // If this is a binary operation of the right kind with only one use then // add its operands to the expression. - if (BinaryOperator *BO = isReassociableOp(Op, Opcode)) { + if (Instruction *BO = isReassociableOp(Op, Opcode)) { assert(Visited.insert(Op).second && "Not first visit!"); LLVM_DEBUG(dbgs() << "DIRECT ADD: " << *Op << " (" << Weight << ")\n"); Worklist.push_back(std::make_pair(BO, Weight)); @@ -572,14 +582,14 @@ // If this is a multiply expression, turn any internal negations into // multiplies by -1 so they can be reassociated. - if (BinaryOperator *BO = dyn_cast(Op)) - if ((Opcode == Instruction::Mul && match(BO, m_Neg(m_Value()))) || - (Opcode == Instruction::FMul && match(BO, m_FNeg(m_Value())))) { + if (Instruction *Neg = dyn_cast(Op)) + if ((Opcode == Instruction::Mul && match(Neg, m_Neg(m_Value()))) || + (Opcode == Instruction::FMul && match(Neg, m_FNeg(m_Value())))) { LLVM_DEBUG(dbgs() << "MORPH LEAF: " << *Op << " (" << Weight << ") TO "); - BO = LowerNegateToMultiply(BO); - LLVM_DEBUG(dbgs() << *BO << '\n'); - Worklist.push_back(std::make_pair(BO, Weight)); + Neg = LowerNegateToMultiply(Neg); + LLVM_DEBUG(dbgs() << *Neg << '\n'); + Worklist.push_back(std::make_pair(Neg, Weight)); Changed = true; continue; } @@ -1963,11 +1973,13 @@ // User must be a binary operator with one or more uses. Instruction *User = I->user_back(); - if (!isa(User) || User->use_empty()) + if ((!isa(User) && !isa(User)) || + User->use_empty()) return nullptr; unsigned UserOpcode = User->getOpcode(); - if (UserOpcode != Instruction::FAdd && UserOpcode != Instruction::FSub) + if (UserOpcode != Instruction::FAdd && UserOpcode != Instruction::FSub && + UserOpcode != Instruction::FNeg) return nullptr; // Subtraction is not commutative. Explicitly, the following transform is @@ -2020,7 +2032,7 @@ /// instructions is not allowed. void ReassociatePass::OptimizeInst(Instruction *I) { // Only consider operations that we understand. - if (!isa(I)) + if (!isa(I) && !isa(I)) return; if (I->getOpcode() == Instruction::Shl && isa(I->getOperand(1))) @@ -2085,7 +2097,8 @@ I = NI; } } - } else if (I->getOpcode() == Instruction::FSub) { + } else if (I->getOpcode() == Instruction::FNeg || + I->getOpcode() == Instruction::FSub) { if (ShouldBreakUpSubtract(I)) { Instruction *NI = BreakUpSubtract(I, RedoInsts); RedoInsts.insert(I); @@ -2094,7 +2107,9 @@ } else if (match(I, m_FNeg(m_Value()))) { // Otherwise, this is a negation. See if the operand is a multiply tree // and if this is not an inner node of a multiply tree. - if (isReassociableOp(I->getOperand(1), Instruction::FMul) && + Value *Op = isa(I) ? I->getOperand(1) : + I->getOperand(0); + if (isReassociableOp(Op, Instruction::FMul) && (!I->hasOneUse() || !isReassociableOp(I->user_back(), Instruction::FMul))) { // If the negate was simplified, revisit the users to see if we can Index: llvm/test/Transforms/Reassociate/fast-basictest.ll =================================================================== --- llvm/test/Transforms/Reassociate/fast-basictest.ll +++ llvm/test/Transforms/Reassociate/fast-basictest.ll @@ -586,12 +586,10 @@ ret float %f } -; FIXME: This reassociation is not working. define float @test18_unary_fneg(float %a, float %b, float %z) { ; CHECK-LABEL: @test18_unary_fneg( -; CHECK-NEXT: [[C:%.*]] = fmul fast float [[Z:%.*]], -4.000000e+01 -; CHECK-NEXT: [[E:%.*]] = fmul fast float [[C]], [[A:%.*]] -; CHECK-NEXT: [[F:%.*]] = fneg fast float [[E]] +; CHECK-NEXT: [[E:%.*]] = fmul fast float [[A:%.*]], 4.000000e+01 +; CHECK-NEXT: [[F:%.*]] = fmul fast float [[E]], [[Z:%.*]] ; CHECK-NEXT: ret float [[F]] ; %d = fmul fast float %z, 4.000000e+01 @@ -616,6 +614,21 @@ ret float %f } +; It is not safe to reassociate unary fneg without nsz and nnan. +define float @test18_reassoc_unary_fneg(float %a, float %b, float %z) { +; CHECK-LABEL: @test18_reassoc_unary_fneg( +; CHECK-NEXT: [[C:%.*]] = fmul reassoc float [[Z:%.*]], -4.000000e+01 +; CHECK-NEXT: [[E:%.*]] = fmul reassoc float [[C]], [[A:%.*]] +; CHECK-NEXT: [[F:%.*]] = fneg reassoc float [[E]] +; CHECK-NEXT: ret float [[F]] +; + %d = fmul reassoc float %z, 4.000000e+01 + %c = fneg reassoc float %d + %e = fmul reassoc float %a, %c + %f = fneg reassoc float %e + ret float %f +} + ; With sub reassociation, constant folding can eliminate the 12 and -12 constants. define float @test19(float %A, float %B) { ; CHECK-LABEL: @test19(