Move from Stage 0 to Stage 1.

Only emit one PHI node for IV uses with identical bases and strides (after
moving foldable immediates to the load/store instruction).

This implements LoopStrengthReduce/dont_insert_redundant_ops.ll, allowing
us to generate this PPC code for test1:

        or r30, r3, r3
.LBB_test1_1:   ; Loop
        li r2, 0
        stw r2, 0(r30)
        stw r2, 4(r30)
        bl L_pred$stub
        addi r30, r30, 8
        cmplwi cr0, r3, 0
        bne .LBB_test1_1        ; Loop

instead of this code:

        or r30, r3, r3
        or r29, r3, r3
.LBB_test1_1:   ; Loop
        li r2, 0
        stw r2, 0(r29)
        stw r2, 4(r30)
        bl L_pred$stub
        addi r30, r30, 8        ;; Two iv's with step of 8
        addi r29, r29, 8
        cmplwi cr0, r3, 0
        bne .LBB_test1_1        ; Loop

llvm-svn: 22635
This commit is contained in:
Chris Lattner 2005-08-03 22:51:21 +00:00
parent 3a18a39587
commit db23c74e5e
1 changed files with 31 additions and 27 deletions

View File

@ -554,24 +554,25 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(Value *Stride,
SomeLoopPHI->getIncomingBlock(SomeLoopPHI->getIncomingBlock(0) == Preheader); SomeLoopPHI->getIncomingBlock(SomeLoopPHI->getIncomingBlock(0) == Preheader);
// FIXME: This loop needs increasing levels of intelligence. // FIXME: This loop needs increasing levels of intelligence.
// STAGE 0: just emit everything as its own base. <-- We are here // STAGE 0: just emit everything as its own base.
// STAGE 1: factor out common vars from bases, and try and push resulting // STAGE 1: factor out common vars from bases, and try and push resulting
// constants into Imm field. // constants into Imm field. <-- We are here
// STAGE 2: factor out large constants to try and make more constants // STAGE 2: factor out large constants to try and make more constants
// acceptable for target loads and stores. // acceptable for target loads and stores.
std::sort(UsersToProcess.begin(), UsersToProcess.end());
// Sort by the base value, so that all IVs with identical bases are next to
// each other.
std::sort(UsersToProcess.begin(), UsersToProcess.end());
while (!UsersToProcess.empty()) { while (!UsersToProcess.empty()) {
SCEVHandle Base = UsersToProcess.front().first;
// Create a new Phi for this base, and stick it in the loop header. // Create a new Phi for this base, and stick it in the loop header.
Value *Replaced = UsersToProcess.front().second.OperandValToReplace; const Type *ReplacedTy = Base->getType();
const Type *ReplacedTy = Replaced->getType(); PHINode *NewPHI = new PHINode(ReplacedTy, "iv.", PhiInsertBefore);
PHINode *NewPHI = new PHINode(ReplacedTy, Replaced->getName()+".str",
PhiInsertBefore);
// Emit the initial base value into the loop preheader, and add it to the // Emit the initial base value into the loop preheader, and add it to the
// Phi node. // Phi node.
Value *BaseV = Rewriter.expandCodeFor(UsersToProcess.front().first, Value *BaseV = Rewriter.expandCodeFor(Base, PreInsertPt, ReplacedTy);
PreInsertPt, ReplacedTy);
NewPHI->addIncoming(BaseV, Preheader); NewPHI->addIncoming(BaseV, Preheader);
// Emit the increment of the base value before the terminator of the loop // Emit the increment of the base value before the terminator of the loop
@ -585,28 +586,31 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(Value *Stride,
NewPHI->addIncoming(IncV, LatchBlock); NewPHI->addIncoming(IncV, LatchBlock);
// Emit the code to add the immediate offset to the Phi value, just before // Emit the code to add the immediate offset to the Phi value, just before
// the instruction that we identified as using this stride and base. // the instructions that we identified as using this stride and base.
// First, empty the SCEVExpander's expression map so that we are guaranteed while (!UsersToProcess.empty() && UsersToProcess.front().first == Base) {
// to have the code emitted where we expect it. BasedUser &User = UsersToProcess.front().second;
Rewriter.clear();
SCEVHandle NewValSCEV = SCEVAddExpr::get(SCEVUnknown::get(NewPHI),
UsersToProcess.front().second.Imm);
Value *newVal = Rewriter.expandCodeFor(NewValSCEV,
UsersToProcess.front().second.Inst,
ReplacedTy);
// Replace the use of the operand Value with the new Phi we just created. // Clear the SCEVExpander's expression map so that we are guaranteed
DEBUG(std::cerr << "REPLACING: " << *Replaced << "IN: " << // to have the code emitted where we expect it.
*UsersToProcess.front().second.Inst << "WITH: "<< *newVal << '\n'); Rewriter.clear();
UsersToProcess.front().second.Inst->replaceUsesOfWith(Replaced, newVal); SCEVHandle NewValSCEV = SCEVAddExpr::get(SCEVUnknown::get(NewPHI),
User.Imm);
Value *Replaced = UsersToProcess.front().second.OperandValToReplace;
Value *newVal = Rewriter.expandCodeFor(NewValSCEV, User.Inst,
Replaced->getType());
// Mark old value we replaced as possibly dead, so that it is elminated // Replace the use of the operand Value with the new Phi we just created.
// if we just replaced the last use of that value. DEBUG(std::cerr << "REPLACING: " << *Replaced << "IN: " <<
DeadInsts.insert(cast<Instruction>(Replaced)); *User.Inst << "WITH: "<< *newVal << '\n');
User.Inst->replaceUsesOfWith(Replaced, newVal);
UsersToProcess.erase(UsersToProcess.begin()); // Mark old value we replaced as possibly dead, so that it is elminated
++NumReduced; // if we just replaced the last use of that value.
DeadInsts.insert(cast<Instruction>(Replaced));
UsersToProcess.erase(UsersToProcess.begin());
++NumReduced;
}
// TODO: Next, find out which base index is the most common, pull it out. // TODO: Next, find out which base index is the most common, pull it out.
} }