From: Chris Lattner Date: Sun, 29 Oct 2006 21:05:41 +0000 (+0000) Subject: Make CanFallThrough more intelligent (so it can handle blocks with (e.g.) no X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6b0e3f890779b7fc912bec8d40a9590e44742737;p=oota-llvm.git Make CanFallThrough more intelligent (so it can handle blocks with (e.g.) no successors), and make island block movement more general. This compiles CodeGen/X86/2006-04-27-ISelFoldingBug.ll to: _loadAndRLEsource_no_exit_2E_1_label_2E_0: subl $8, %esp movl %esi, 4(%esp) movl %ebx, (%esp) movl 16(%esp), %eax movl 12(%esp), %ecx LBB1_3: #label.0 movl _last, %edx movl %edx, %esi incl %esi movl %esi, _last movl %ecx, %ebx # TRUNCATE movb %bl, %bl movl _block, %esi movb %bl, 1(%esi,%edx) cmpl %eax, _last jge LBB1_2 #codeRepl5.exitStub LBB1_4: #label.0 cmpl $257, %ecx je LBB1_2 #codeRepl5.exitStub LBB1_1: #label.0.no_exit.1_crit_edge.exitStub movl $1, %eax movl (%esp), %ebx movl 4(%esp), %esi addl $8, %esp ret LBB1_2: #codeRepl5.exitStub xorl %eax, %eax movl (%esp), %ebx movl 4(%esp), %esi addl $8, %esp ret instead of: _loadAndRLEsource_no_exit_2E_1_label_2E_0: subl $8, %esp movl %esi, 4(%esp) movl %ebx, (%esp) movl 16(%esp), %eax movl 12(%esp), %ecx jmp LBB1_3 #label.0 LBB1_1: #label.0.no_exit.1_crit_edge.exitStub movl $1, %eax movl (%esp), %ebx movl 4(%esp), %esi addl $8, %esp ret LBB1_2: #codeRepl5.exitStub xorl %eax, %eax movl (%esp), %ebx movl 4(%esp), %esi addl $8, %esp ret LBB1_3: #label.0 movl _last, %edx movl %edx, %esi incl %esi movl %esi, _last movl %ecx, %ebx # TRUNCATE movb %bl, %bl movl _block, %esi movb %bl, 1(%esi,%edx) cmpl %eax, _last jge LBB1_2 #codeRepl5.exitStub LBB1_4: #label.0 cmpl $257, %ecx jne LBB1_1 #label.0.no_exit.1_crit_edge.exitStub jmp LBB1_2 #codeRepl5.exitStub ... which is much better layout :) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31282 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp index dc527b9fd54..9ca0091d203 100644 --- a/lib/CodeGen/BranchFolding.cpp +++ b/lib/CodeGen/BranchFolding.cpp @@ -48,6 +48,11 @@ namespace { bool OptimizeBranches(MachineFunction &MF); void OptimizeBlock(MachineBasicBlock *MBB); void RemoveDeadBlock(MachineBasicBlock *MBB); + + bool CanFallThrough(MachineBasicBlock *CurBB); + bool CanFallThrough(MachineBasicBlock *CurBB, bool BranchUnAnalyzable, + MachineBasicBlock *TBB, MachineBasicBlock *FBB, + const std::vector &Cond); }; } @@ -443,19 +448,37 @@ static void ReplaceUsesOfBlockWith(MachineBasicBlock *BB, } } -/// CanFallThrough - Return true of the specified branch condition can transfer -/// control to FallthroughBlock, the block immediately after the branch. -static bool CanFallThrough(MachineBasicBlock *TBB, - MachineBasicBlock *FBB, - const std::vector &Cond, - MachineFunction::iterator FallthroughBlock) { +/// CanFallThrough - Return true if the specified block (with the specified +/// branch condition) can implicitly transfer control to the block after it by +/// falling off the end of it. This should return false if it can reach the +/// block after it, but it uses an explicit branch to do so (e.g. a table jump). +/// +/// True is a conservative answer. +/// +bool BranchFolder::CanFallThrough(MachineBasicBlock *CurBB, + bool BranchUnAnalyzable, + MachineBasicBlock *TBB, MachineBasicBlock *FBB, + const std::vector &Cond) { + MachineFunction::iterator Fallthrough = CurBB; + ++Fallthrough; + // If FallthroughBlock is off the end of the function, it can't fall through. + if (Fallthrough == CurBB->getParent()->end()) + return false; + + // If FallthroughBlock isn't a successor of CurBB, no fallthrough is possible. + if (!CurBB->isSuccessor(Fallthrough)) + return false; + + // If we couldn't analyze the branch, assume it could fall through. + if (BranchUnAnalyzable) return true; + // If there is no branch, control always falls through. if (TBB == 0) return true; // If there is some explicit branch to the fallthrough block, it can obviously // reach, even though the branch should get folded to fall through implicitly. - if (MachineFunction::iterator(TBB) == FallthroughBlock || - MachineFunction::iterator(FBB) == FallthroughBlock) + if (MachineFunction::iterator(TBB) == Fallthrough || + MachineFunction::iterator(FBB) == Fallthrough) return true; // If it's an unconditional branch to some block not the fall through, it @@ -467,6 +490,20 @@ static bool CanFallThrough(MachineBasicBlock *TBB, return FBB == 0; } +/// CanFallThrough - Return true if the specified can implicitly transfer +/// control to the block after it by falling off the end of it. This should +/// return false if it can reach the block after it, but it uses an explicit +/// branch to do so (e.g. a table jump). +/// +/// True is a conservative answer. +/// +bool BranchFolder::CanFallThrough(MachineBasicBlock *CurBB) { + MachineBasicBlock *TBB = 0, *FBB = 0; + std::vector Cond; + bool CurUnAnalyzable = TII->AnalyzeBranch(*CurBB, TBB, FBB, Cond); + return CanFallThrough(CurBB, CurUnAnalyzable, TBB, FBB, Cond); +} + /// OptimizeBlock - Analyze and optimize control flow related to the specified /// block. This is never called on the entry block. void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) { @@ -504,8 +541,8 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) { MachineBasicBlock *PriorTBB = 0, *PriorFBB = 0; std::vector PriorCond; - bool PriorUnAnalyzable = false; - PriorUnAnalyzable = TII->AnalyzeBranch(PrevBB, PriorTBB, PriorFBB, PriorCond); + bool PriorUnAnalyzable = + TII->AnalyzeBranch(PrevBB, PriorTBB, PriorFBB, PriorCond); if (!PriorUnAnalyzable) { // If the CFG for the prior block has extra edges, remove them. MadeChange |= CorrectExtraCFGEdges(PrevBB, PriorTBB, PriorFBB, @@ -561,7 +598,8 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) { // Analyze the branch in the current block. MachineBasicBlock *CurTBB = 0, *CurFBB = 0; std::vector CurCond; - if (!TII->AnalyzeBranch(*MBB, CurTBB, CurFBB, CurCond)) { + bool CurUnAnalyzable = TII->AnalyzeBranch(*MBB, CurTBB, CurFBB, CurCond); + if (!CurUnAnalyzable) { // If the CFG for the prior block has extra edges, remove them. MadeChange |= CorrectExtraCFGEdges(*MBB, CurTBB, CurFBB, !CurCond.empty(), @@ -630,62 +668,56 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) { // Add the branch back if the block is more than just an uncond branch. TII->InsertBranch(*MBB, CurTBB, 0, CurCond); } - - // If the prior block doesn't fall through into this block, and if this - // block doesn't fall through into some other block, see if we can find a - // place to move this block where a fall-through will happen. - if (!PriorUnAnalyzable && !CanFallThrough(PriorTBB, PriorFBB, - PriorCond, MBB)) { - // Now we know that there was no fall-through into this block, check to - // see if it has fall-throughs. - if (!CanFallThrough(CurTBB, CurFBB, CurCond, FallThrough)) { - - // Check all the predecessors of this block. If one of them has no fall - // throughs, move this block right after it. - for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), - E = MBB->pred_end(); PI != E; ++PI) { - // Analyze the branch at the end of the pred. - MachineBasicBlock *PredBB = *PI; - MachineFunction::iterator PredFallthrough = PredBB; ++PredFallthrough; - MachineBasicBlock *PredTBB = 0, *PredFBB = 0; - std::vector PredCond; - if (PredBB != MBB && - !TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond) && - !CanFallThrough(PredTBB, PredFBB, PredCond, PredFallthrough)) { - MBB->moveAfter(PredBB); - MadeChange = true; - return OptimizeBlock(MBB); - } - } - - // Check all successors to see if we can move this block before it. - for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), - E = MBB->succ_end(); SI != E; ++SI) { - // Analyze the branch at the end of the block before the succ. - MachineBasicBlock *SuccBB = *SI; - MachineFunction::iterator SuccPrev = SuccBB; --SuccPrev; - MachineBasicBlock *SuccPrevTBB = 0, *SuccPrevFBB = 0; - std::vector SuccPrevCond; - if (SuccBB != MBB && - !TII->AnalyzeBranch(*SuccPrev, SuccPrevTBB, SuccPrevFBB, - SuccPrevCond) && - !CanFallThrough(SuccPrevTBB, SuccPrevFBB, SuccPrevCond, SuccBB)) { - MBB->moveBefore(SuccBB); - MadeChange = true; - return OptimizeBlock(MBB); - } + } + + // If the prior block doesn't fall through into this block, and if this + // block doesn't fall through into some other block, see if we can find a + // place to move this block where a fall-through will happen. + if (!CanFallThrough(&PrevBB, PriorUnAnalyzable, + PriorTBB, PriorFBB, PriorCond)) { + // Now we know that there was no fall-through into this block, check to + // see if it has a fall-through into its successor. + if (!CanFallThrough(MBB, CurUnAnalyzable, CurTBB, CurFBB, CurCond)) { + // Check all the predecessors of this block. If one of them has no fall + // throughs, move this block right after it. + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + E = MBB->pred_end(); PI != E; ++PI) { + // Analyze the branch at the end of the pred. + MachineBasicBlock *PredBB = *PI; + MachineFunction::iterator PredFallthrough = PredBB; ++PredFallthrough; + MachineBasicBlock *PredTBB = 0, *PredFBB = 0; + std::vector PredCond; + if (PredBB != MBB && !CanFallThrough(PredBB)) { + MBB->moveAfter(PredBB); + MadeChange = true; + return OptimizeBlock(MBB); } + } - // Okay, there is no really great place to put this block. If, however, - // the block before this one would be a fall-through if this block were - // removed, move this block to the end of the function. - if (FallThrough != MBB->getParent()->end() && - CanFallThrough(PriorTBB, PriorFBB, PriorCond, FallThrough)) { - MBB->moveAfter(--MBB->getParent()->end()); + // Check all successors to see if we can move this block before it. + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + E = MBB->succ_end(); SI != E; ++SI) { + // Analyze the branch at the end of the block before the succ. + MachineBasicBlock *SuccBB = *SI; + MachineFunction::iterator SuccPrev = SuccBB; --SuccPrev; + MachineBasicBlock *SuccPrevTBB = 0, *SuccPrevFBB = 0; + std::vector SuccPrevCond; + if (SuccBB != MBB && !CanFallThrough(SuccPrev)) { + MBB->moveBefore(SuccBB); MadeChange = true; - return; + return OptimizeBlock(MBB); } } + + // Okay, there is no really great place to put this block. If, however, + // the block before this one would be a fall-through if this block were + // removed, move this block to the end of the function. + if (FallThrough != MBB->getParent()->end() && + PrevBB.isSuccessor(FallThrough)) { + MBB->moveAfter(--MBB->getParent()->end()); + MadeChange = true; + return; + } } } }