From 0a16da445740ca6fcd7a7ca571c1917e77315904 Mon Sep 17 00:00:00 2001 From: Nadav Rotem Date: Wed, 12 Sep 2012 04:57:37 +0000 Subject: [PATCH] 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 --- lib/CodeGen/StackColoring.cpp | 47 +++++++++++++++++++++++++++++++ test/CodeGen/X86/StackColoring.ll | 30 ++++++++++++++++++-- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/StackColoring.cpp b/lib/CodeGen/StackColoring.cpp index 6df932c1ae0..16b715a7962 100644 --- a/lib/CodeGen/StackColoring.cpp +++ b/lib/CodeGen/StackColoring.cpp @@ -158,6 +158,14 @@ private: /// slots to use the joint slots. void remapInstructions(DenseMap &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. /// A->B->C becomes A->C. void expungeSlotMap(DenseMap &SlotRemap, unsigned NumSlots); @@ -543,6 +551,43 @@ void StackColoring::remapInstructions(DenseMap &SlotRemap) { DEBUG(dbgs()<<"Fixed "<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 #"< &SlotRemap, unsigned NumSlots) { // Expunge slot remap map. @@ -617,6 +662,8 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) { // Propagate the liveness information. calculateLiveIntervals(NumSlots); + removeInvalidSlotRanges(); + // Maps old slots to new slots. DenseMap SlotRemap; unsigned RemovedSlots = 0; diff --git a/test/CodeGen/X86/StackColoring.ll b/test/CodeGen/X86/StackColoring.ll index 0f36ce29b9a..a83a4ebbe2e 100644 --- a/test/CodeGen/X86/StackColoring.ll +++ b/test/CodeGen/X86/StackColoring.ll @@ -7,7 +7,6 @@ target triple = "x86_64-apple-macosx10.8.0" ;YESCOLOR: subq $136, %rsp ;NOCOLOR: subq $264, %rsp - define i32 @myCall_w2(i32 %in) { entry: %a = alloca [17 x i8*], align 8 @@ -328,7 +327,6 @@ entry: ;YESCOLOR: subq $272, %rsp ;NOCOLOR: subq $272, %rsp - define i32 @myCall_end_before_begin(i32 %in, i1 %d) { entry: %a = alloca [17 x i8*], align 8 @@ -352,11 +350,37 @@ bb3: 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 @llvm.lifetime.start(i64, i8* nocapture) nounwind declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind - declare i32 @foo(i32, i8*) +declare i32 @foo(i32, i8*)