forked from OSchip/llvm-project
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:
parent
03bdd8f797
commit
d76755ec95
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue