From 1452d46e0bc5ca6bea77ca85abf9b694e3b6ab84 Mon Sep 17 00:00:00 2001 From: Preston Gurd Date: Fri, 11 Jan 2013 22:06:56 +0000 Subject: [PATCH] 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 --- lib/Target/X86/X86PadShortFunction.cpp | 77 +++++++++++++++----- test/CodeGen/X86/atom-pad-short-functions.ll | 25 +++++++ 2 files changed, 84 insertions(+), 18 deletions(-) diff --git a/lib/Target/X86/X86PadShortFunction.cpp b/lib/Target/X86/X86PadShortFunction.cpp index c22872f1280..83e75ea994c 100644 --- a/lib/Target/X86/X86PadShortFunction.cpp +++ b/lib/Target/X86/X86PadShortFunction.cpp @@ -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 ReturnBBs; + // VisitedBBs - Cache of previously visited BBs. + DenseMap 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::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::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; } diff --git a/test/CodeGen/X86/atom-pad-short-functions.ll b/test/CodeGen/X86/atom-pad-short-functions.ll index 54af17d4c4f..b9a39e08cb5 100644 --- a/test/CodeGen/X86/atom-pad-short-functions.ll +++ b/test/CodeGen/X86/atom-pad-short-functions.ll @@ -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 +} + -- 2.34.1