Stack coloring: remove lifetime intervals which contain escaped allocas.

The input program may contain intructions which are not inside lifetime
markers. This can happen due to a bug in the compiler or due to a bug in
user code (for example, returning a reference to a local variable).
This commit adds checks that all of the instructions in the function and
invalidates lifetime ranges which do not contain all of the instructions.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163678 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nadav Rotem
2012-09-12 04:57:37 +00:00
parent 2c57a334d7
commit 0a16da4457
2 changed files with 74 additions and 3 deletions

View File

@@ -158,6 +158,14 @@ private:
/// slots to use the joint slots. /// slots to use the joint slots.
void remapInstructions(DenseMap<int, int> &SlotRemap); void remapInstructions(DenseMap<int, int> &SlotRemap);
/// The input program may contain intructions which are not inside lifetime
/// markers. This can happen due to a bug in the compiler or due to a bug in
/// user code (for example, returning a reference to a local variable).
/// This procedure checks all of the instructions in the function and
/// invalidates lifetime ranges which do not contain all of the instructions
/// which access that frame slot.
void removeInvalidSlotRanges();
/// Map entries which point to other entries to their destination. /// Map entries which point to other entries to their destination.
/// A->B->C becomes A->C. /// A->B->C becomes A->C.
void expungeSlotMap(DenseMap<int, int> &SlotRemap, unsigned NumSlots); void expungeSlotMap(DenseMap<int, int> &SlotRemap, unsigned NumSlots);
@@ -543,6 +551,43 @@ void StackColoring::remapInstructions(DenseMap<int, int> &SlotRemap) {
DEBUG(dbgs()<<"Fixed "<<FixedInstr<<" machine instructions.\n"); DEBUG(dbgs()<<"Fixed "<<FixedInstr<<" machine instructions.\n");
} }
void StackColoring::removeInvalidSlotRanges() {
MachineFunction::iterator BB, BBE;
MachineBasicBlock::iterator I, IE;
for (BB = MF->begin(), BBE = MF->end(); BB != BBE; ++BB)
for (I = BB->begin(), IE = BB->end(); I != IE; ++I) {
if (I->getOpcode() == TargetOpcode::LIFETIME_START ||
I->getOpcode() == TargetOpcode::LIFETIME_END || I->isDebugValue())
continue;
// Check all of the machine operands.
for (unsigned i = 0 ; i < I->getNumOperands(); ++i) {
MachineOperand &MO = I->getOperand(i);
if (!MO.isFI())
continue;
int Slot = MO.getIndex();
if (Slot<0)
continue;
if (Intervals[Slot]->empty())
continue;
// Check that the used slot is inside the calculated lifetime range.
// If it is not, warn about it and invalidate the range.
LiveInterval *Interval = Intervals[Slot];
SlotIndex Index = Indexes->getInstructionIndex(I);
if (Interval->find(Index) == Interval->end()) {
Intervals[Slot]->clear();
DEBUG(dbgs()<<"Invalidating range #"<<Slot<<"\n");
}
}
}
}
void StackColoring::expungeSlotMap(DenseMap<int, int> &SlotRemap, void StackColoring::expungeSlotMap(DenseMap<int, int> &SlotRemap,
unsigned NumSlots) { unsigned NumSlots) {
// Expunge slot remap map. // Expunge slot remap map.
@@ -617,6 +662,8 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) {
// Propagate the liveness information. // Propagate the liveness information.
calculateLiveIntervals(NumSlots); calculateLiveIntervals(NumSlots);
removeInvalidSlotRanges();
// Maps old slots to new slots. // Maps old slots to new slots.
DenseMap<int, int> SlotRemap; DenseMap<int, int> SlotRemap;
unsigned RemovedSlots = 0; unsigned RemovedSlots = 0;

View File

@@ -7,7 +7,6 @@ target triple = "x86_64-apple-macosx10.8.0"
;YESCOLOR: subq $136, %rsp ;YESCOLOR: subq $136, %rsp
;NOCOLOR: subq $264, %rsp ;NOCOLOR: subq $264, %rsp
define i32 @myCall_w2(i32 %in) { define i32 @myCall_w2(i32 %in) {
entry: entry:
%a = alloca [17 x i8*], align 8 %a = alloca [17 x i8*], align 8
@@ -328,7 +327,6 @@ entry:
;YESCOLOR: subq $272, %rsp ;YESCOLOR: subq $272, %rsp
;NOCOLOR: subq $272, %rsp ;NOCOLOR: subq $272, %rsp
define i32 @myCall_end_before_begin(i32 %in, i1 %d) { define i32 @myCall_end_before_begin(i32 %in, i1 %d) {
entry: entry:
%a = alloca [17 x i8*], align 8 %a = alloca [17 x i8*], align 8
@@ -352,11 +350,37 @@ bb3:
ret i32 0 ret i32 0
} }
; Check that we don't assert and crash even when there are allocas
; outside the declared lifetime regions.
;YESCOLOR: bad_range
;NOCOLOR: bad_range
define void @bad_range() nounwind ssp {
entry:
%A.i1 = alloca [100 x i32], align 4
%B.i2 = alloca [100 x i32], align 4
%A.i = alloca [100 x i32], align 4
%B.i = alloca [100 x i32], align 4
%0 = bitcast [100 x i32]* %A.i to i8*
call void @llvm.lifetime.start(i64 -1, i8* %0) nounwind
%1 = bitcast [100 x i32]* %B.i to i8*
call void @llvm.lifetime.start(i64 -1, i8* %1) nounwind
call void @bar([100 x i32]* %A.i, [100 x i32]* %B.i) nounwind
call void @llvm.lifetime.end(i64 -1, i8* %0) nounwind
call void @llvm.lifetime.end(i64 -1, i8* %1) nounwind
br label %block2
block2:
; I am used outside the marked lifetime.
call void @bar([100 x i32]* %A.i, [100 x i32]* %B.i) nounwind
ret void
}
declare void @bar([100 x i32]* , [100 x i32]*) nounwind declare void @bar([100 x i32]* , [100 x i32]*) nounwind
declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind
declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind
declare i32 @foo(i32, i8*) declare i32 @foo(i32, i8*)