Update patch for the pad short functions pass for Intel Atom (only).

Adds a check for -Oz, changes the code to not re-visit BBs,
and skips over DBG_VALUE instrs.

Patch by Andy Zhang.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172258 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Preston Gurd
2013-01-11 22:06:56 +00:00
parent 8ecd3be1f3
commit 1452d46e0b
2 changed files with 84 additions and 18 deletions

View File

@@ -33,6 +33,19 @@ using namespace llvm;
STATISTIC(NumBBsPadded, "Number of basic blocks padded");
namespace {
struct VisitedBBInfo {
// HasReturn - Whether the BB contains a return instruction
bool HasReturn;
// Cycles - Number of cycles until return if HasReturn is true, otherwise
// number of cycles until end of the BB
unsigned int Cycles;
VisitedBBInfo() : HasReturn(false), Cycles(0) {}
VisitedBBInfo(bool HasReturn, unsigned int Cycles)
: HasReturn(HasReturn), Cycles(Cycles) {}
};
struct PadShortFunc : public MachineFunctionPass {
static char ID;
PadShortFunc() : MachineFunctionPass(ID)
@@ -49,16 +62,21 @@ namespace {
unsigned int Cycles = 0);
bool cyclesUntilReturn(MachineBasicBlock *MBB,
unsigned int &Cycles,
MachineBasicBlock::iterator *Location = 0);
unsigned int &Cycles);
void addPadding(MachineBasicBlock *MBB,
MachineBasicBlock::iterator &MBBI,
unsigned int NOOPsToAdd);
const unsigned int Threshold;
// ReturnBBs - Maps basic blocks that return to the minimum number of
// cycles until the return, starting from the entry block.
DenseMap<MachineBasicBlock*, unsigned int> ReturnBBs;
// VisitedBBs - Cache of previously visited BBs.
DenseMap<MachineBasicBlock*, VisitedBBInfo> VisitedBBs;
const TargetMachine *TM;
const TargetInstrInfo *TII;
};
@@ -73,25 +91,26 @@ FunctionPass *llvm::createX86PadShortFunctions() {
/// runOnMachineFunction - Loop over all of the basic blocks, inserting
/// NOOP instructions before early exits.
bool PadShortFunc::runOnMachineFunction(MachineFunction &MF) {
bool OptForSize = MF.getFunction()->getAttributes().
hasAttribute(AttributeSet::FunctionIndex, Attribute::OptimizeForSize);
if (OptForSize)
const AttributeSet &FnAttrs = MF.getFunction()->getAttributes();
if (FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::OptimizeForSize) ||
FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::MinSize)) {
return false;
}
TM = &MF.getTarget();
TII = TM->getInstrInfo();
// Search through basic blocks and mark the ones that have early returns
ReturnBBs.clear();
VisitedBBs.clear();
findReturns(MF.begin());
bool MadeChange = false;
MachineBasicBlock::iterator ReturnLoc;
MachineBasicBlock *MBB;
unsigned int Cycles = 0;
unsigned int BBCycles;
// Pad the identified basic blocks with NOOPs
for (DenseMap<MachineBasicBlock*, unsigned int>::iterator I = ReturnBBs.begin();
@@ -100,8 +119,16 @@ bool PadShortFunc::runOnMachineFunction(MachineFunction &MF) {
Cycles = I->second;
if (Cycles < Threshold) {
if (!cyclesUntilReturn(MBB, BBCycles, &ReturnLoc))
continue;
// BB ends in a return. Skip over any DBG_VALUE instructions
// trailing the terminator.
assert(MBB->size() > 0 &&
"Basic block should contain at least a RET but is empty");
MachineBasicBlock::iterator ReturnLoc = --MBB->end();
while (ReturnLoc->isDebugValue())
--ReturnLoc;
assert(ReturnLoc->isReturn() && !ReturnLoc->isCall() &&
"Basic block does not end with RET");
addPadding(MBB, ReturnLoc, Threshold - Cycles);
NumBBsPadded++;
@@ -127,18 +154,30 @@ void PadShortFunc::findReturns(MachineBasicBlock *MBB, unsigned int Cycles) {
// Follow branches in BB and look for returns
for (MachineBasicBlock::succ_iterator I = MBB->succ_begin();
I != MBB->succ_end(); ++I) {
I != MBB->succ_end(); ++I) {
if (*I == MBB)
continue;
findReturns(*I, Cycles);
}
}
/// cyclesUntilReturn - if the MBB has a return instruction, set Location
/// to the instruction and return true. Return false otherwise.
/// cyclesUntilReturn - return true if the MBB has a return instruction,
/// and return false otherwise.
/// Cycles will be incremented by the number of cycles taken to reach the
/// return or the end of the BB, whichever occurs first.
bool PadShortFunc::cyclesUntilReturn(MachineBasicBlock *MBB,
unsigned int &Cycles,
MachineBasicBlock::iterator *Location) {
unsigned int &Cycles) {
// Return cached result if BB was previously visited
DenseMap<MachineBasicBlock*, VisitedBBInfo>::iterator it
= VisitedBBs.find(MBB);
if (it != VisitedBBs.end()) {
VisitedBBInfo BBInfo = it->second;
Cycles += BBInfo.Cycles;
return BBInfo.HasReturn;
}
unsigned int CyclesToEnd = 0;
for (MachineBasicBlock::iterator MBBI = MBB->begin();
MBBI != MBB->end(); ++MBBI) {
MachineInstr *MI = MBBI;
@@ -146,14 +185,16 @@ bool PadShortFunc::cyclesUntilReturn(MachineBasicBlock *MBB,
// functions do not count because the called function will be padded,
// if necessary.
if (MI->isReturn() && !MI->isCall()) {
if (Location)
*Location = MBBI;
VisitedBBs[MBB] = VisitedBBInfo(true, CyclesToEnd);
Cycles += CyclesToEnd;
return true;
}
Cycles += TII->getInstrLatency(TM->getInstrItineraryData(), MI);
CyclesToEnd += TII->getInstrLatency(TM->getInstrItineraryData(), MI);
}
VisitedBBs[MBB] = VisitedBBInfo(false, CyclesToEnd);
Cycles += CyclesToEnd;
return false;
}

View File

@@ -22,6 +22,13 @@ define i32 @test_optsize(i32 %a) nounwind optsize {
ret i32 %a
}
define i32 @test_minsize(i32 %a) nounwind minsize {
; CHECK: test_minsize
; CHECK: movl
; CHECK-NEXT: ret
ret i32 %a
}
define i32 @test_add(i32 %a, i32 %b) nounwind {
; CHECK: test_add
; CHECK: addl
@@ -76,3 +83,21 @@ if.end:
ret void
}
define void @test_branch_to_same_bb(i32 %x, i32 %y) nounwind {
; CHECK: @test_branch_to_same_bb
%cmp = icmp sgt i32 %x, 0
br i1 %cmp, label %while.cond, label %while.end
while.cond:
br label %while.cond
; CHECK: nop
; CHECK: nop
; CHECK: nop
; CHECK: nop
; CHECK: ret
while.end:
ret void
}