From 0cd19b93017fcaba737b15ea4da39c460feb5670 Mon Sep 17 00:00:00 2001 From: Nadav Rotem Date: Thu, 13 Sep 2012 12:38:37 +0000 Subject: [PATCH] Stack Coloring: We have code that checks that all of the uses of allocas are within the lifetime zone. Sometime legitimate usages of allocas are hoisted outside of the lifetime zone. For example, GEPS may calculate the address of a member of an allocated struct. This commit makes sure that we only check (abort regions or assert) for instructions that read and write memory using stack frames directly. Notice that by allowing legitimate usages outside the lifetime zone we also stop checking for instructions which use derivatives of allocas. We will catch less bugs in user code and in the compiler itself. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163791 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/StackColoring.cpp | 22 +++++++++++++++++----- test/CodeGen/X86/StackColoring.ll | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/lib/CodeGen/StackColoring.cpp b/lib/CodeGen/StackColoring.cpp index a14d730025f..1a7801abd8a 100644 --- a/lib/CodeGen/StackColoring.cpp +++ b/lib/CodeGen/StackColoring.cpp @@ -73,7 +73,6 @@ STATISTIC(StackSlotMerged, "Number of stack slot merged."); STATISTIC(EscapedAllocas, "Number of allocas that escaped the lifetime region"); - //===----------------------------------------------------------------------===// // StackColoring Pass //===----------------------------------------------------------------------===// @@ -259,8 +258,8 @@ unsigned StackColoring::collectMarkers(unsigned NumSlot) { 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 #"<getName()<<"\n"); } if (IsStart) { @@ -538,8 +537,12 @@ void StackColoring::remapInstructions(DenseMap &SlotRemap) { // 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]; assert(Interval->find(Index) != Interval->end() && @@ -569,6 +572,15 @@ void StackColoring::removeInvalidSlotRanges() { 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 instrucitons 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); @@ -652,7 +664,7 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) { DEBUG(dbgs()<<"Total Stack size: "<