static cl::opt<bool>
DisableColoring("no-stack-coloring",
- cl::init(true), cl::Hidden,
- cl::desc("Suppress stack coloring"));
+ cl::init(false), cl::Hidden,
+ cl::desc("Disable stack coloring"));
-STATISTIC(NumMarkerSeen, "Number of life markers found.");
+static cl::opt<bool>
+CheckEscapedAllocas("stack-coloring-check-escaped",
+ cl::init(true), cl::Hidden,
+ cl::desc("Look for allocas which escaped the lifetime region"));
+
+STATISTIC(NumMarkerSeen, "Number of lifetime markers found.");
STATISTIC(StackSpaceSaved, "Number of bytes saved due to merging slots.");
STATISTIC(StackSlotMerged, "Number of stack slot merged.");
+STATISTIC(EscapedAllocas,
+ "Number of allocas that escaped the lifetime region");
//===----------------------------------------------------------------------===//
// StackColoring Pass
/// VNInfo is used for the construction of LiveIntervals.
VNInfo::Allocator VNInfoAllocator;
/// SlotIndex analysis object.
- SlotIndexes* Indexes;
+ SlotIndexes *Indexes;
/// The list of lifetime markers found. These markers are to be removed
/// once the coloring is done.
const Value *Allocation = MFI->getObjectAllocation(Slot);
if (Allocation) {
- DEBUG(dbgs()<<"Found lifetime marker for allocation: "<<
- Allocation->getName()<<"\n");
+ DEBUG(dbgs()<<"Found a lifetime marker for slot #"<<Slot<<
+ " with allocation: "<< Allocation->getName()<<"\n");
}
if (IsStart) {
// inside the expected live range. If the instruction is not inside
// the calculated range then it means that the alloca usage moved
// outside of the lifetime markers.
+ // NOTE: Alloca address calculations which happen outside the lifetime
+ // zone are are okay, despite the fact that we don't have a good way
+ // for validating all of the usages of the calculation.
#ifndef NDEBUG
- if (!I->isDebugValue()) {
+ bool TouchesMemory = I->mayLoad() || I->mayStore();
+ if (!I->isDebugValue() && TouchesMemory) {
SlotIndex Index = Indexes->getInstructionIndex(I);
- LiveInterval* Interval = Intervals[FromSlot];
+ LiveInterval *Interval = Intervals[FromSlot];
assert(Interval->find(Index) != Interval->end() &&
"Found instruction usage outside of live range.");
}
I->getOpcode() == TargetOpcode::LIFETIME_END || I->isDebugValue())
continue;
+ // Some intervals are suspicious! In some cases we find address
+ // calculations outside of the lifetime zone, but not actual memory
+ // read or write. Memory accesses outside of the lifetime zone are a clear
+ // violation, but address calculations are okay. This can happen when
+ // GEPs are hoisted outside of the lifetime zone.
+ // So, in here we only check instructions which can read or write memory.
+ if (!I->mayLoad() && !I->mayStore())
+ continue;
+
// Check all of the machine operands.
for (unsigned i = 0 ; i < I->getNumOperands(); ++i) {
MachineOperand &MO = I->getOperand(i);
if (Interval->find(Index) == Interval->end()) {
Intervals[Slot]->clear();
DEBUG(dbgs()<<"Invalidating range #"<<Slot<<"\n");
+ EscapedAllocas++;
}
}
}
DEBUG(dbgs()<<"Total Stack size: "<<TotalSize<<" bytes\n\n");
// Don't continue because there are not enough lifetime markers, or the
- // stack or too small, or we are told not to optimize the slots.
+ // stack is too small, or we are told not to optimize the slots.
if (NumMarkers < 2 || TotalSize < 16 || DisableColoring) {
DEBUG(dbgs()<<"Will not try to merge slots.\n");
return removeAllMarkers();
// Propagate the liveness information.
calculateLiveIntervals(NumSlots);
- removeInvalidSlotRanges();
+ // Search for allocas which are used outside of the declared lifetime
+ // markers.
+ if (CheckEscapedAllocas)
+ removeInvalidSlotRanges();
// Maps old slots to new slots.
DenseMap<int, int> SlotRemap;