IfConversion: Handle inclusive ranges more carefully.

This may affect calculations for thresholds, but is not a significant change
in behavior.

The problem was that an inclusive range must have an additonal flag to showr
that it is empty, because otherwise begin == end implies that the range has one
element, and it may not be possible to move past on either side.

llvm-svn: 279166
This commit is contained in:
Kyle Butt 2016-08-18 22:09:23 +00:00
parent 03bdd8f797
commit d76755ec95
1 changed files with 56 additions and 22 deletions

View File

@ -15,6 +15,7 @@
#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/Passes.h"
#include "BranchFolding.h" #include "BranchFolding.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/LivePhysRegs.h"
@ -550,16 +551,32 @@ static inline bool skipDebugInstructionsForward(
return It == End; return It == End;
} }
/// Decrement \p It until it points to a non-debug instruction or to \p Begin. /// Shrink the provided inclusive range by one instruction.
/// If the range was one instruction (\p It == \p Begin), It is not modified,
/// but \p Empty is set to true.
static inline void shrinkInclusiveRange(
MachineBasicBlock::iterator &Begin,
MachineBasicBlock::iterator &It,
bool &Empty) {
if (It == Begin)
Empty = true;
else
It--;
}
/// Decrement \p It until it points to a non-debug instruction or the range is
/// empty.
/// @param It Iterator to decrement. /// @param It Iterator to decrement.
/// @param Begin Iterator that points to beginning. Will be compared to It /// @param Begin Iterator that points to beginning. Will be compared to It
/// @returns true if It == Begin, false otherwise. /// @param Empty Set to true if the resulting range is Empty
/// @returns the value of Empty as a convenience.
static inline bool skipDebugInstructionsBackward( static inline bool skipDebugInstructionsBackward(
MachineBasicBlock::iterator &Begin,
MachineBasicBlock::iterator &It, MachineBasicBlock::iterator &It,
MachineBasicBlock::iterator &Begin) { bool &Empty) {
while (It != Begin && It->isDebugValue()) while (!Empty && It->isDebugValue())
It--; shrinkInclusiveRange(Begin, It, Empty);
return It == Begin; return Empty;
} }
/// Count duplicated instructions and move the iterators to show where they /// Count duplicated instructions and move the iterators to show where they
@ -596,41 +613,58 @@ static void countDuplicatedInstructions(
++FIB; ++FIB;
} }
// Now, in preparation for counting duplicate instructions at the ends of the
// blocks, move the end iterators up past any branch instructions.
// If both blocks are returning don't skip the branches, since they will // If both blocks are returning don't skip the branches, since they will
// likely be both identical return instructions. In such cases the return // likely be both identical return instructions. In such cases the return
// can be left unpredicated. // can be left unpredicated.
// Check for already containing all of the block. // Check for already containing all of the block.
if (TIB == TIE || FIB == FIE) if (TIB == TIE || FIB == FIE)
return; return;
// Now, in preparation for counting duplicate instructions at the ends of the
// blocks, move the end iterators up past any branch instructions.
--TIE; --TIE;
--FIE; --FIE;
// After this point TIB and TIE define an inclusive range, which means that
// TIB == TIE is true when there is one more instruction to consider, not at
// the end. Because we may not be able to go before TIB, we need a flag to
// indicate a completely empty range.
bool TEmpty = false, FEmpty = false;
// Upon exit TIE and FIE will both point at the last non-shared instruction.
// They need to be moved forward to point past the last non-shared
// instruction if the range they delimit is non-empty.
auto IncrementEndIteratorsOnExit = make_scope_exit([&]() {
if (!TEmpty)
++TIE;
if (!FEmpty)
++FIE;
});
if (!TBB.succ_empty() || !FBB.succ_empty()) { if (!TBB.succ_empty() || !FBB.succ_empty()) {
if (SkipConditionalBranches) { if (SkipConditionalBranches) {
while (TIE != TIB && TIE->isBranch()) while (!TEmpty && TIE->isBranch())
--TIE; shrinkInclusiveRange(TIB, TIE, TEmpty);
while (FIE != FIB && FIE->isBranch()) while (!FEmpty && FIE->isBranch())
--FIE; shrinkInclusiveRange(FIB, FIE, FEmpty);
} else { } else {
while (TIE != TIB && TIE->isUnconditionalBranch()) while (!TEmpty && TIE->isUnconditionalBranch())
--TIE; shrinkInclusiveRange(TIB, TIE, TEmpty);
while (FIE != FIB && FIE->isUnconditionalBranch()) while (!FEmpty && FIE->isUnconditionalBranch())
--FIE; shrinkInclusiveRange(FIB, FIE, FEmpty);
} }
} }
// If Dups1 includes all of a block, then don't count duplicate // If Dups1 includes all of a block, then don't count duplicate
// instructions at the end of the blocks. // instructions at the end of the blocks.
if (TIB == TIE || FIB == FIE) if (TEmpty || FEmpty)
return; return;
// Count duplicate instructions at the ends of the blocks. // Count duplicate instructions at the ends of the blocks.
while (TIE != TIB && FIE != FIB) { while (!TEmpty && !FEmpty) {
// Skip dbg_value instructions. These do not count. // Skip dbg_value instructions. These do not count.
if (skipDebugInstructionsBackward(TIE, TIB)) if (skipDebugInstructionsBackward(TIB, TIE, TEmpty))
break; break;
if (skipDebugInstructionsBackward(FIE, FIB)) if (skipDebugInstructionsBackward(FIB, FIE, FEmpty))
break; break;
if (!TIE->isIdenticalTo(*FIE)) if (!TIE->isIdenticalTo(*FIE))
break; break;
@ -638,8 +672,8 @@ static void countDuplicatedInstructions(
// still don't want to count them. // still don't want to count them.
if (SkipConditionalBranches || !TIE->isBranch()) if (SkipConditionalBranches || !TIE->isBranch())
++Dups2; ++Dups2;
--TIE; shrinkInclusiveRange(TIB, TIE, TEmpty);
--FIE; shrinkInclusiveRange(FIB, FIE, FEmpty);
} }
} }