mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-27 06:35:30 +00:00
cd2ae14ce3
header is just the entry block to the loop, and it needn't be at the top of the loop in the code layout. Remove the code that suppressed loop alignment for outer loops, so that outer loops are aligned. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84158 91177308-0d34-0410-b5e6-96231b3b80d8
318 lines
9.2 KiB
C++
318 lines
9.2 KiB
C++
//===-- CodePlacementOpt.cpp - Code Placement pass. -----------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the pass that optimize code placement and align loop
|
|
// headers to target specific alignment boundary.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#define DEBUG_TYPE "code-placement"
|
|
#include "llvm/CodeGen/MachineLoopInfo.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/Target/TargetInstrInfo.h"
|
|
#include "llvm/Target/TargetLowering.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/ADT/Statistic.h"
|
|
using namespace llvm;
|
|
|
|
STATISTIC(NumLoopsAligned, "Number of loops aligned");
|
|
STATISTIC(NumIntraElim, "Number of intra loop branches eliminated");
|
|
STATISTIC(NumIntraMoved, "Number of intra loop branches moved");
|
|
|
|
namespace {
|
|
class CodePlacementOpt : public MachineFunctionPass {
|
|
const MachineLoopInfo *MLI;
|
|
const TargetInstrInfo *TII;
|
|
const TargetLowering *TLI;
|
|
|
|
/// ChangedMBBs - BBs which are modified by OptimizeIntraLoopEdges.
|
|
SmallPtrSet<MachineBasicBlock*, 8> ChangedMBBs;
|
|
|
|
/// UncondJmpMBBs - A list of BBs which are in loops and end with
|
|
/// unconditional branches.
|
|
SmallVector<std::pair<MachineBasicBlock*,MachineBasicBlock*>, 4>
|
|
UncondJmpMBBs;
|
|
|
|
public:
|
|
static char ID;
|
|
CodePlacementOpt() : MachineFunctionPass(&ID) {}
|
|
|
|
virtual bool runOnMachineFunction(MachineFunction &MF);
|
|
virtual const char *getPassName() const {
|
|
return "Code Placement Optimizater";
|
|
}
|
|
|
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AU.addRequired<MachineLoopInfo>();
|
|
AU.addPreservedID(MachineDominatorsID);
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
}
|
|
|
|
private:
|
|
bool OptimizeIntraLoopEdges();
|
|
bool AlignLoops(MachineFunction &MF);
|
|
bool AlignLoop(MachineFunction &MF, MachineLoop *L, unsigned Align);
|
|
};
|
|
|
|
char CodePlacementOpt::ID = 0;
|
|
} // end anonymous namespace
|
|
|
|
FunctionPass *llvm::createCodePlacementOptPass() {
|
|
return new CodePlacementOpt();
|
|
}
|
|
|
|
/// OptimizeBackEdges - Place loop back edges to move unconditional branches
|
|
/// out of the loop.
|
|
///
|
|
/// A:
|
|
/// ...
|
|
/// <fallthrough to B>
|
|
///
|
|
/// B: --> loop header
|
|
/// ...
|
|
/// jcc <cond> C, [exit]
|
|
///
|
|
/// C:
|
|
/// ...
|
|
/// jmp B
|
|
///
|
|
/// ==>
|
|
///
|
|
/// A:
|
|
/// ...
|
|
/// jmp B
|
|
///
|
|
/// C:
|
|
/// ...
|
|
/// <fallthough to B>
|
|
///
|
|
/// B: --> loop header
|
|
/// ...
|
|
/// jcc <cond> C, [exit]
|
|
///
|
|
bool CodePlacementOpt::OptimizeIntraLoopEdges() {
|
|
if (!TLI->shouldOptimizeCodePlacement())
|
|
return false;
|
|
|
|
bool Changed = false;
|
|
for (unsigned i = 0, e = UncondJmpMBBs.size(); i != e; ++i) {
|
|
MachineBasicBlock *MBB = UncondJmpMBBs[i].first;
|
|
MachineBasicBlock *SuccMBB = UncondJmpMBBs[i].second;
|
|
MachineLoop *L = MLI->getLoopFor(MBB);
|
|
assert(L && "BB is expected to be in a loop!");
|
|
|
|
if (ChangedMBBs.count(MBB)) {
|
|
// BB has been modified, re-analyze.
|
|
MachineBasicBlock *TBB = 0, *FBB = 0;
|
|
SmallVector<MachineOperand, 4> Cond;
|
|
if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond) || !Cond.empty())
|
|
continue;
|
|
if (MLI->getLoopFor(TBB) != L || TBB->isLandingPad())
|
|
continue;
|
|
SuccMBB = TBB;
|
|
} else {
|
|
assert(MLI->getLoopFor(SuccMBB) == L &&
|
|
"Successor is not in the same loop!");
|
|
}
|
|
|
|
if (MBB->isLayoutSuccessor(SuccMBB)) {
|
|
// Successor is right after MBB, just eliminate the unconditional jmp.
|
|
// Can this happen?
|
|
TII->RemoveBranch(*MBB);
|
|
ChangedMBBs.insert(MBB);
|
|
++NumIntraElim;
|
|
Changed = true;
|
|
continue;
|
|
}
|
|
|
|
// Now check if the predecessor is fallthrough from any BB. If there is,
|
|
// that BB should be from outside the loop since edge will become a jmp.
|
|
bool OkToMove = true;
|
|
MachineBasicBlock *FtMBB = 0, *FtTBB = 0, *FtFBB = 0;
|
|
SmallVector<MachineOperand, 4> FtCond;
|
|
for (MachineBasicBlock::pred_iterator PI = SuccMBB->pred_begin(),
|
|
PE = SuccMBB->pred_end(); PI != PE; ++PI) {
|
|
MachineBasicBlock *PredMBB = *PI;
|
|
if (PredMBB->isLayoutSuccessor(SuccMBB)) {
|
|
if (TII->AnalyzeBranch(*PredMBB, FtTBB, FtFBB, FtCond)) {
|
|
OkToMove = false;
|
|
break;
|
|
}
|
|
if (!FtTBB)
|
|
FtTBB = SuccMBB;
|
|
else if (!FtFBB) {
|
|
assert(FtFBB != SuccMBB && "Unexpected control flow!");
|
|
FtFBB = SuccMBB;
|
|
}
|
|
|
|
// A fallthrough.
|
|
FtMBB = PredMBB;
|
|
MachineLoop *PL = MLI->getLoopFor(PredMBB);
|
|
if (PL && (PL == L || PL->getLoopDepth() >= L->getLoopDepth()))
|
|
OkToMove = false;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!OkToMove)
|
|
continue;
|
|
|
|
// Is it profitable? If SuccMBB can fallthrough itself, that can be changed
|
|
// into a jmp.
|
|
MachineBasicBlock *TBB = 0, *FBB = 0;
|
|
SmallVector<MachineOperand, 4> Cond;
|
|
if (TII->AnalyzeBranch(*SuccMBB, TBB, FBB, Cond))
|
|
continue;
|
|
if (!TBB && Cond.empty())
|
|
TBB = next(MachineFunction::iterator(SuccMBB));
|
|
else if (!FBB && !Cond.empty())
|
|
FBB = next(MachineFunction::iterator(SuccMBB));
|
|
|
|
// This calculate the cost of the transformation. Also, it finds the *only*
|
|
// intra-loop edge if there is one.
|
|
int Cost = 0;
|
|
bool HasOneIntraSucc = true;
|
|
MachineBasicBlock *IntraSucc = 0;
|
|
for (MachineBasicBlock::succ_iterator SI = SuccMBB->succ_begin(),
|
|
SE = SuccMBB->succ_end(); SI != SE; ++SI) {
|
|
MachineBasicBlock *SSMBB = *SI;
|
|
if (MLI->getLoopFor(SSMBB) == L) {
|
|
if (!IntraSucc)
|
|
IntraSucc = SSMBB;
|
|
else
|
|
HasOneIntraSucc = false;
|
|
}
|
|
|
|
if (SuccMBB->isLayoutSuccessor(SSMBB))
|
|
// This will become a jmp.
|
|
++Cost;
|
|
else if (MBB->isLayoutSuccessor(SSMBB)) {
|
|
// One of the successor will become the new fallthrough.
|
|
if (SSMBB == FBB) {
|
|
FBB = 0;
|
|
--Cost;
|
|
} else if (!FBB && SSMBB == TBB && Cond.empty()) {
|
|
TBB = 0;
|
|
--Cost;
|
|
} else if (!Cond.empty() && !TII->ReverseBranchCondition(Cond)) {
|
|
assert(SSMBB == TBB);
|
|
TBB = FBB;
|
|
FBB = 0;
|
|
--Cost;
|
|
}
|
|
}
|
|
}
|
|
if (Cost)
|
|
continue;
|
|
|
|
// Now, let's move the successor to below the BB to eliminate the jmp.
|
|
SuccMBB->moveAfter(MBB);
|
|
TII->RemoveBranch(*MBB);
|
|
TII->RemoveBranch(*SuccMBB);
|
|
if (TBB)
|
|
TII->InsertBranch(*SuccMBB, TBB, FBB, Cond);
|
|
ChangedMBBs.insert(MBB);
|
|
ChangedMBBs.insert(SuccMBB);
|
|
if (FtMBB) {
|
|
TII->RemoveBranch(*FtMBB);
|
|
TII->InsertBranch(*FtMBB, FtTBB, FtFBB, FtCond);
|
|
ChangedMBBs.insert(FtMBB);
|
|
}
|
|
Changed = true;
|
|
}
|
|
|
|
++NumIntraMoved;
|
|
return Changed;
|
|
}
|
|
|
|
/// AlignLoops - Align loop headers to target preferred alignments.
|
|
///
|
|
bool CodePlacementOpt::AlignLoops(MachineFunction &MF) {
|
|
const Function *F = MF.getFunction();
|
|
if (F->hasFnAttr(Attribute::OptimizeForSize))
|
|
return false;
|
|
|
|
unsigned Align = TLI->getPrefLoopAlignment();
|
|
if (!Align)
|
|
return false; // Don't care about loop alignment.
|
|
|
|
bool Changed = false;
|
|
|
|
for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end();
|
|
I != E; ++I)
|
|
Changed |= AlignLoop(MF, *I, Align);
|
|
|
|
return Changed;
|
|
}
|
|
|
|
bool CodePlacementOpt::AlignLoop(MachineFunction &MF, MachineLoop *L,
|
|
unsigned Align) {
|
|
bool Changed = false;
|
|
|
|
// Do alignment for nested loops.
|
|
for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I)
|
|
Changed |= AlignLoop(MF, *I, Align);
|
|
|
|
MachineBasicBlock *TopMBB = L->getHeader();
|
|
if (TopMBB == MF.begin()) return Changed;
|
|
|
|
MachineBasicBlock *PredMBB = prior(MachineFunction::iterator(TopMBB));
|
|
while (MLI->getLoopFor(PredMBB) == L) {
|
|
TopMBB = PredMBB;
|
|
if (TopMBB == MF.begin()) return Changed;
|
|
PredMBB = prior(MachineFunction::iterator(TopMBB));
|
|
}
|
|
|
|
TopMBB->setAlignment(Align);
|
|
Changed = true;
|
|
++NumLoopsAligned;
|
|
|
|
return Changed;
|
|
}
|
|
|
|
bool CodePlacementOpt::runOnMachineFunction(MachineFunction &MF) {
|
|
MLI = &getAnalysis<MachineLoopInfo>();
|
|
if (MLI->empty())
|
|
return false; // No loops.
|
|
|
|
TLI = MF.getTarget().getTargetLowering();
|
|
TII = MF.getTarget().getInstrInfo();
|
|
|
|
// Analyze the BBs first and keep track of BBs that
|
|
// end with an unconditional jmp to another block in the same loop.
|
|
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
|
|
MachineBasicBlock *MBB = I;
|
|
if (MBB->isLandingPad())
|
|
continue;
|
|
MachineLoop *L = MLI->getLoopFor(MBB);
|
|
if (!L)
|
|
continue;
|
|
|
|
MachineBasicBlock *TBB = 0, *FBB = 0;
|
|
SmallVector<MachineOperand, 4> Cond;
|
|
if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond) || !Cond.empty())
|
|
continue;
|
|
if (MLI->getLoopFor(TBB) == L && !TBB->isLandingPad())
|
|
UncondJmpMBBs.push_back(std::make_pair(MBB, TBB));
|
|
}
|
|
|
|
bool Changed = OptimizeIntraLoopEdges();
|
|
|
|
Changed |= AlignLoops(MF);
|
|
|
|
ChangedMBBs.clear();
|
|
UncondJmpMBBs.clear();
|
|
|
|
return Changed;
|
|
}
|