llvm.org GIT mirror llvm / 180b545
[Reassociate] Handle unary FNeg in the Reassociate pass Differential Revision: https://reviews.llvm.org/D63445 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363813 91177308-0d34-0410-b5e6-96231b3b80d8 Cameron McInally 2 months ago
2 changed file(s) with 45 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
265265
266266 /// Replace 0-X with X*-1.
267267 static BinaryOperator *LowerNegateToMultiply(Instruction *Neg) {
268 assert((isa(Neg) || isa(Neg)) &&
269 "Expected a Negate!");
270 // It's not safe to lower a unary FNeg into a FMul by -1.0. However,
271 // we can only reach this function with fast flags set, so it's
272 // safe to do with nnan.
273 assert((!isa(Neg) || Neg->isFast()) &&
274 "Expecting FastMathFlags!");
275 unsigned OpNo = isa(Neg) ? 1 : 0;
268276 Type *Ty = Neg->getType();
269277 Constant *NegOne = Ty->isIntOrIntVectorTy() ?
270278 ConstantInt::getAllOnesValue(Ty) : ConstantFP::get(Ty, -1.0);
271279
272 BinaryOperator *Res = CreateMul(Neg->getOperand(1), NegOne, "", Neg, Neg);
273 Neg->setOperand(1, Constant::getNullValue(Ty)); // Drop use of op.
280 BinaryOperator *Res = CreateMul(Neg->getOperand(OpNo), NegOne, "", Neg, Neg);
281 Neg->setOperand(OpNo, Constant::getNullValue(Ty)); // Drop use of op.
274282 Res->takeName(Neg);
275283 Neg->replaceAllUsesWith(Res);
276284 Res->setDebugLoc(Neg->getDebugLoc());
443451 /// that have all uses inside the expression (i.e. only used by non-leaf nodes
444452 /// of the expression) if it can turn them into binary operators of the right
445453 /// type and thus make the expression bigger.
446 static bool LinearizeExprTree(BinaryOperator *I,
454 static bool LinearizeExprTree(Instruction *I,
447455 SmallVectorImpl &Ops) {
456 assert((isa(I) || isa(I)) &&
457 "Expected a UnaryOperator or BinaryOperator!");
448458 LLVM_DEBUG(dbgs() << "LINEARIZE: " << *I << '\n');
449459 unsigned Bitwidth = I->getType()->getScalarType()->getPrimitiveSizeInBits();
450460 unsigned Opcode = I->getOpcode();
461471 // with their weights, representing a certain number of paths to the operator.
462472 // If an operator occurs in the worklist multiple times then we found multiple
463473 // ways to get to it.
464 SmallVectorBinaryOperator*, APInt>, 8> Worklist; // (Op, Weight)
474 SmallVectorInstruction*, APInt>, 8> Worklist; // (Op, Weight)
465475 Worklist.push_back(std::make_pair(I, APInt(Bitwidth, 1)));
466476 bool Changed = false;
467477
488498 SmallPtrSet Visited; // For sanity checking the iteration scheme.
489499 #endif
490500 while (!Worklist.empty()) {
491 std::pair<BinaryOperator*, APInt> P = Worklist.pop_back_val();
501 std::pair<Instruction*, APInt> P = Worklist.pop_back_val();
492502 I = P.first; // We examine the operands of this binary operator.
493503
494 for (unsigned OpIdx = 0; OpIdx < 2; ++OpIdx) { // Visit operands.
504 for (unsigned OpIdx = 0; OpIdx < I->getNumOperands(); ++OpIdx) { // Visit operands.
495505 Value *Op = I->getOperand(OpIdx);
496506 APInt Weight = P.second; // Number of paths to this operand.
497507 LLVM_DEBUG(dbgs() << "OPERAND: " << *Op << " (" << Weight << ")\n");
571581
572582 // If this is a multiply expression, turn any internal negations into
573583 // multiplies by -1 so they can be reassociated.
574 if (BinaryOperator *BO = dyn_cast(Op))
575 if ((Opcode == Instruction::Mul && match(BO, m_Neg(m_Value()))) ||
576 (Opcode == Instruction::FMul && match(BO, m_FNeg(m_Value())))) {
584 if (Instruction *Tmp = dyn_cast(Op))
585 if ((Opcode == Instruction::Mul && match(Tmp, m_Neg(m_Value()))) ||
586 (Opcode == Instruction::FMul && match(Tmp, m_FNeg(m_Value())))) {
577587 LLVM_DEBUG(dbgs()
578588 << "MORPH LEAF: " << *Op << " (" << Weight << ") TO ");
579 BO = LowerNegateToMultiply(BO);
580 LLVM_DEBUG(dbgs() << *BO << '\n');
581 Worklist.push_back(std::make_pair(BO, Weight));
589 Tmp = LowerNegateToMultiply(Tmp);
590 LLVM_DEBUG(dbgs() << *Tmp << '\n');
591 Worklist.push_back(std::make_pair(Tmp, Weight));
582592 Changed = true;
583593 continue;
584594 }
20192029 /// instructions is not allowed.
20202030 void ReassociatePass::OptimizeInst(Instruction *I) {
20212031 // Only consider operations that we understand.
2022 if (!isa<BinaryOperator>(I))
2032 if (!isa<UnaryOperator>(I) && !isa<BinaryOperator>(I))
20232033 return;
20242034
20252035 if (I->getOpcode() == Instruction::Shl && isa(I->getOperand(1)))
20842094 I = NI;
20852095 }
20862096 }
2087 } else if (I->getOpcode() == Instruction::FSub) {
2097 } else if (I->getOpcode() == Instruction::FNeg ||
2098 I->getOpcode() == Instruction::FSub) {
20882099 if (ShouldBreakUpSubtract(I)) {
20892100 Instruction *NI = BreakUpSubtract(I, RedoInsts);
20902101 RedoInsts.insert(I);
20932104 } else if (match(I, m_FNeg(m_Value()))) {
20942105 // Otherwise, this is a negation. See if the operand is a multiply tree
20952106 // and if this is not an inner node of a multiply tree.
2096 if (isReassociableOp(I->getOperand(1), Instruction::FMul) &&
2107 Value *Op = isa(I) ? I->getOperand(1) :
2108 I->getOperand(0);
2109 if (isReassociableOp(Op, Instruction::FMul) &&
20972110 (!I->hasOneUse() ||
20982111 !isReassociableOp(I->user_back(), Instruction::FMul))) {
20992112 // If the negate was simplified, revisit the users to see if we can
585585 ret float %f
586586 }
587587
588 ; FIXME: This reassociation is not working.
589588 define float @test18_unary_fneg(float %a, float %b, float %z) {
590589 ; CHECK-LABEL: @test18_unary_fneg(
591 ; CHECK-NEXT: [[C:%.*]] = fmul fast float [[Z:%.*]], -4.000000e+01
592 ; CHECK-NEXT: [[E:%.*]] = fmul fast float [[C]], [[A:%.*]]
593 ; CHECK-NEXT: [[F:%.*]] = fneg fast float [[E]]
590 ; CHECK-NEXT: [[E:%.*]] = fmul fast float [[A:%.*]], 4.000000e+01
591 ; CHECK-NEXT: [[F:%.*]] = fmul fast float [[E]], [[Z:%.*]]
594592 ; CHECK-NEXT: ret float [[F]]
595593 ;
596594 %d = fmul fast float %z, 4.000000e+01
612610 %c = fsub reassoc float 0.000000e+00, %d
613611 %e = fmul reassoc float %a, %c
614612 %f = fsub reassoc float 0.000000e+00, %e
613 ret float %f
614 }
615
616 ; It is not safe to reassociate unary fneg without nnan.
617 define float @test18_reassoc_unary_fneg(float %a, float %b, float %z) {
618 ; CHECK-LABEL: @test18_reassoc_unary_fneg(
619 ; CHECK-NEXT: [[C:%.*]] = fmul reassoc float [[Z:%.*]], -4.000000e+01
620 ; CHECK-NEXT: [[E:%.*]] = fmul reassoc float [[C]], [[A:%.*]]
621 ; CHECK-NEXT: [[F:%.*]] = fneg reassoc float [[E]]
622 ; CHECK-NEXT: ret float [[F]]
623 ;
624 %d = fmul reassoc float %z, 4.000000e+01
625 %c = fneg reassoc float %d
626 %e = fmul reassoc float %a, %c
627 %f = fneg reassoc float %e
615628 ret float %f
616629 }
617630