[llvm-commits] [llvm] r44687 - in /llvm/trunk: include/llvm/CodeGen/Passes.h lib/CodeGen/LLVMTargetMachine.cpp lib/CodeGen/MachineLICM.cpp lib/Target/PowerPC/PPCInstrInfo.td
Bill Wendling
isanbard at gmail.com
Fri Dec 7 17:43:02 PST 2007
On Dec 7, 2007 4:42 PM, Evan Cheng <evan.cheng at apple.com> wrote:
>
> Nicely done!
>
Thx! :-)
> > + // Map the def of a virtual register to the machine instruction.
> > + std::map<unsigned, const MachineInstr*> VRegDefs;
>
> Consider using IndexedMap.
>
Okay.
> > + bool CanHoistInst(MachineInstr &I) const {
> > + const TargetInstrDescriptor *TID = I.getInstrDescriptor();
> > + MachineOpCode Opcode = TID->Opcode;
> > +
> > + return TII->isTriviallyReMaterializable(&I) &&
> > + // FIXME: Below necessary?
> > + !(TII->isReturn(Opcode) ||
> > + TII->isTerminatorInstr(Opcode) ||
> > + TII->isBranch(Opcode) ||
> > + TII->isIndirectBranch(Opcode) ||
> > + TII->isBarrier(Opcode) ||
> > + TII->isCall(Opcode) ||
> > + TII->isLoad(Opcode) || // TODO: Do loads and stores.
> > + TII->isStore(Opcode));
> > + }
>
> Since you are touching this... When you have a chance, please rename
> it to something like hasNoSideEffect().
>
Okay. I'll do it in a future patch.
> > + void MoveInstToBlock(MachineBasicBlock *MBB, MachineInstr *MI) {
> > + MachineBasicBlock::iterator Iter = MBB->getFirstTerminator();
> > + MBB->insert(Iter, MI);
> > + }
>
> Poorly named. :-) MoveInstToEndOfBlock?
>
Sounds good.
> > + // Visit all of the instructions of the loop. We want to visit
> > the subloops
> > + // first, though, so that we can hoist their invariants first
> > into their
> > + // containing loop before we process that loop.
> > + SmallVector<MachineLoop*, 16> Loops;
> > + GatherAllLoops(L, Loops);
>
> Seems to me this can be smarter. When you are gathering the loops, put
> loops of greater depth in the front of the queue then HoistRegion
> won't have to check if the BB is in the current loop level?
>
> > + for (MachineBasicBlock::const_iterator
> > + II = MBB.begin(), IE = MBB.end(); II != IE; ++II) {
> > + const MachineInstr &MI = *II;
> > +
> > + if (MI.getNumOperands() > 0) {
> > + const MachineOperand &MO = MI.getOperand(0);
>
> This is not right. You are assuming only one def and it must be the
> first operand. Neither is necessarily true.
>
Okay.
> > + // If this subregion is not in the top level loop at all, exit.
> > + if (!CurLoop->contains(BB)) return;
> > +
> > + // Only need to process the contents of this block if it is not
> > part of a
> > + // subloop (which would already have been processed).
> > + if (!isInSubLoop(BB))
>
> Like I said earlier, I think this check can be eliminated if we visit
> the inner most loops first (and perhaps keep track which BB has been
> processed?)
>
I'm not sure I understand. I was under the impression that
MachineDomTreeNode would give blocks from the loop and its subloops.
If we keep track of those visited, I suppose we could simplify this
check...
> > + // Try hoisting the instruction out of the loop. We can only
> > do this if
> > + // all of the operands of the instruction are loop invariant
> > and if it is
> > + // safe to hoist the instruction.
> > + if (Hoist(MI))
> > + // Hoisting was successful! Remove bothersome instruction
> > now.
> > + MI.getParent()->remove(&MI);
>
> Why not have Hoist remove the MI?
>
I had a bug earlier where I was invalidating an iterator. I think it's
no longer the case, so this can be moved to Hoist instead.
> > + // Don't hoist if this instruction implicitly reads physical
> > registers or
> > + // doesn't take any operands.
> > + if (TID->ImplicitUses || !I.getNumOperands()) return false;
>
> The comment is wrong. It's ok to lift something that has no uses but
> produces result(s), right? "doesn't take any operands" to me means
> something that doesn't have any uses.
>
I was thinking about things like "emms" which don't seem to use
anything, but have definite side effects. Or will this be picked up in
the earlier check isTriviallyReMaterializable?
> > + if (!CanHoistInst(I)) return false;
>
> Perhaps fold the earlier check into CanHoistInst()?
>
Okay.
> > + // If the loop contains the definition of an operand, then the
> > instruction
> > + // isn't loop invariant.
> > + if (CurLoop->contains(VRegDefs[Reg]->getParent()))
> > + return false;
>
> Hmmm. I am not sure about this. What if the definition is in the
> preheader? Does contains() returns true? Chris, Owen?
>
The preheader wouldn't be part of the loop, so it should be okay.
> Also, I fear this might be slow. When you are creating the VReg -> MI
> map, perhaps you should create a VReg -> loop map as well?
>
I'll see if a map will help things along.
> > +bool MachineLICM::Hoist(MachineInstr &MI) {
> > + if (!isLoopInvariantInst(MI)) return false;
> > +
> > + std::vector<MachineBasicBlock*> Preds;
> > +
> > + // Non-back-edge predecessors.
> > + FindPredecessors(Preds);
>
> Consider caching some of these info?
>
Okay.
> > + // FIXME: We are assuming at first that the basic blocks coming
> > into this
> > + // loop have only one successor each. This isn't the case in
> > general because
> > + // we haven't broken critical edges or added preheaders.
> > + if (MBB->succ_size() != 1) return false;
> > + assert(*MBB->succ_begin() == CurLoop->getHeader() &&
> > + "The predecessor doesn't feed directly into the loop
> > header!");
> > + }
>
> Are we going to create a preheader to hoist LICM to? Then we won't
> need to do all these checking? I am entirely sure about it. Someone
> please chime in.
>
We want a pre-header. That will come at a later time. I just wanted to
"walk" before running. :-) But, yes, a lot of the checks for
predecessors will be simplified then.
> > + // Now move the instructions to the predecessors.
> > + for (std::vector<MachineBasicBlock*>::iterator
> > + I = Preds.begin(), E = Preds.end(); I != E; ++I)
> > + MoveInstToBlock(*I, MI.clone());
>
> This will create multiple copies, it seems bad. Again, this should be
> fixable with a loop preheader?
>
As Chris pointed out, it's filled with fail because of phi nodes, etc.
I made it more strict wrt the predecessors. Now there can only be one
(like in Highlander). Eventually, that one will be the pre-header.
> Very nice first cut!
>
Thanks! :-)
-bw
More information about the llvm-commits
mailing list