|
| 1 | +# Description : FDiv is replaced with multiplication by reciprocal and invariant |
| 2 | +# reciprocal is hoisted out of the loop, while multiplication remains |
| 3 | +# even if invariant. |
| 4 | + |
| 5 | + |
| 6 | +diff -Naur --strip-trailing-cr a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp |
| 7 | +--- a/lib/Transforms/Scalar/LICM.cpp 2018-08-09 14:04:49.868088200 -0700 |
| 8 | ++++ b/lib/Transforms/Scalar/LICM.cpp 2018-08-09 13:57:15.100467100 -0700 |
| 9 | +@@ -435,59 +435,72 @@ |
| 10 | + // Only need to process the contents of this block if it is not part of a |
| 11 | + // subloop (which would already have been processed). |
| 12 | + |
| 13 | +- if (!inSubLoop(BB, CurLoop, LI)) |
| 14 | +- for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) { |
| 15 | +- Instruction &I = *II++; |
| 16 | +- // Try constant folding this instruction. If all the operands are |
| 17 | +- // constants, it is technically hoistable, but it would be better to |
| 18 | +- // just fold it. |
| 19 | +- if (Constant *C = ConstantFoldInstruction( |
| 20 | +- &I, I.getModule()->getDataLayout(), TLI)) { |
| 21 | +- DEBUG(dbgs() << "LICM folding inst: " << I << " --> " << *C << '\n'); |
| 22 | +- CurAST->copyValue(&I, C); |
| 23 | +- I.replaceAllUsesWith(C); |
| 24 | +- if (isInstructionTriviallyDead(&I, TLI)) { |
| 25 | +- CurAST->deleteValue(&I); |
| 26 | +- I.eraseFromParent(); |
| 27 | +- } |
| 28 | +- Changed = true; |
| 29 | +- continue; |
| 30 | +- } |
| 31 | ++ if (inSubLoop(BB, CurLoop, LI)) |
| 32 | ++ continue; |
| 33 | + |
| 34 | +- // Attempt to remove floating point division out of the loop by |
| 35 | +- // converting it to a reciprocal multiplication. |
| 36 | +- if (I.getOpcode() == Instruction::FDiv && |
| 37 | +- CurLoop->isLoopInvariant(I.getOperand(1)) && |
| 38 | +- I.hasAllowReciprocal()) { |
| 39 | +- auto Divisor = I.getOperand(1); |
| 40 | +- auto One = llvm::ConstantFP::get(Divisor->getType(), 1.0); |
| 41 | +- auto ReciprocalDivisor = BinaryOperator::CreateFDiv(One, Divisor); |
| 42 | +- ReciprocalDivisor->setFastMathFlags(I.getFastMathFlags()); |
| 43 | +- ReciprocalDivisor->insertBefore(&I); |
| 44 | +- |
| 45 | +- auto Product = |
| 46 | +- BinaryOperator::CreateFMul(I.getOperand(0), ReciprocalDivisor); |
| 47 | +- Product->setFastMathFlags(I.getFastMathFlags()); |
| 48 | +- Product->insertAfter(&I); |
| 49 | +- I.replaceAllUsesWith(Product); |
| 50 | ++ // Keep track of whether the prefix of instructions visited so far are such |
| 51 | ++ // that the next instruction visited is guaranteed to execute if the loop |
| 52 | ++ // is entered. |
| 53 | ++ bool IsMustExecute = CurLoop->getHeader() == BB; |
| 54 | ++ |
| 55 | ++ for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) { |
| 56 | ++ Instruction &I = *II++; |
| 57 | ++ // Try constant folding this instruction. If all the operands are |
| 58 | ++ // constants, it is technically hoistable, but it would be better to |
| 59 | ++ // just fold it. |
| 60 | ++ if (Constant *C = ConstantFoldInstruction( |
| 61 | ++ &I, I.getModule()->getDataLayout(), TLI)) { |
| 62 | ++ DEBUG(dbgs() << "LICM folding inst: " << I << " --> " << *C << '\n'); |
| 63 | ++ CurAST->copyValue(&I, C); |
| 64 | ++ I.replaceAllUsesWith(C); |
| 65 | ++ if (isInstructionTriviallyDead(&I, TLI)) { |
| 66 | ++ CurAST->deleteValue(&I); |
| 67 | + I.eraseFromParent(); |
| 68 | +- |
| 69 | +- hoist(*ReciprocalDivisor, DT, CurLoop, SafetyInfo, ORE); |
| 70 | +- Changed = true; |
| 71 | +- continue; |
| 72 | + } |
| 73 | ++ Changed = true; |
| 74 | ++ continue; |
| 75 | ++ } |
| 76 | ++ |
| 77 | ++ // Try hoisting the instruction out to the preheader. We can only do |
| 78 | ++ // this if all of the operands of the instruction are loop invariant and |
| 79 | ++ // if it is safe to hoist the instruction. |
| 80 | ++ // |
| 81 | ++ if (CurLoop->hasLoopInvariantOperands(&I) && |
| 82 | ++ canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, SafetyInfo, ORE) && |
| 83 | ++ (IsMustExecute || |
| 84 | ++ isSafeToExecuteUnconditionally( |
| 85 | ++ I, DT, CurLoop, SafetyInfo, ORE, |
| 86 | ++ CurLoop->getLoopPreheader()->getTerminator()))) { |
| 87 | ++ Changed |= hoist(I, DT, CurLoop, SafetyInfo, ORE); |
| 88 | ++ continue; |
| 89 | ++ } |
| 90 | + |
| 91 | +- // Try hoisting the instruction out to the preheader. We can only do |
| 92 | +- // this if all of the operands of the instruction are loop invariant and |
| 93 | +- // if it is safe to hoist the instruction. |
| 94 | +- // |
| 95 | +- if (CurLoop->hasLoopInvariantOperands(&I) && |
| 96 | +- canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, SafetyInfo, ORE) && |
| 97 | +- isSafeToExecuteUnconditionally( |
| 98 | +- I, DT, CurLoop, SafetyInfo, ORE, |
| 99 | +- CurLoop->getLoopPreheader()->getTerminator())) |
| 100 | +- Changed |= hoist(I, DT, CurLoop, SafetyInfo, ORE); |
| 101 | ++ // Attempt to remove floating point division out of the loop by |
| 102 | ++ // converting it to a reciprocal multiplication. |
| 103 | ++ if (I.getOpcode() == Instruction::FDiv && |
| 104 | ++ CurLoop->isLoopInvariant(I.getOperand(1)) && |
| 105 | ++ I.hasAllowReciprocal()) { |
| 106 | ++ auto Divisor = I.getOperand(1); |
| 107 | ++ auto One = llvm::ConstantFP::get(Divisor->getType(), 1.0); |
| 108 | ++ auto ReciprocalDivisor = BinaryOperator::CreateFDiv(One, Divisor); |
| 109 | ++ ReciprocalDivisor->setFastMathFlags(I.getFastMathFlags()); |
| 110 | ++ ReciprocalDivisor->insertBefore(&I); |
| 111 | ++ |
| 112 | ++ auto Product = |
| 113 | ++ BinaryOperator::CreateFMul(I.getOperand(0), ReciprocalDivisor); |
| 114 | ++ Product->setFastMathFlags(I.getFastMathFlags()); |
| 115 | ++ Product->insertAfter(&I); |
| 116 | ++ I.replaceAllUsesWith(Product); |
| 117 | ++ I.eraseFromParent(); |
| 118 | ++ |
| 119 | ++ hoist(*ReciprocalDivisor, DT, CurLoop, SafetyInfo, ORE); |
| 120 | ++ Changed = true; |
| 121 | ++ continue; |
| 122 | + } |
| 123 | ++ |
| 124 | ++ if (IsMustExecute) |
| 125 | ++ IsMustExecute = isGuaranteedToTransferExecutionToSuccessor(&I); |
| 126 | ++ } |
| 127 | + } |
| 128 | + |
| 129 | + return Changed; |
0 commit comments