Skip to content

Commit 7c277da

Browse files
committed
Add a new optimization pass: Stack Coloring, that merges disjoint static allocations (allocas). Allocas are known to be
disjoint if they are marked by disjoint lifetime markers (@llvm.lifetime.XXX intrinsics). llvm-svn: 163299
1 parent 34e9931 commit 7c277da

22 files changed

+1057
-16
lines changed

llvm/docs/ReleaseNotes.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,13 @@ <h3>
499499

500500
<div>
501501

502+
<p>Stack Coloring - We have implemented a new optimization pass
503+
to merge stack objects which are used in disjoin areas of the code.
504+
This optimization reduces the required stack space significantly, in cases
505+
where it is clear to the optimizer that the stack slot is not shared.
506+
We use the lifetime markers to tell the codegen that a certain alloca
507+
is used within a region.</p>
508+
502509
<p>We have put a significant amount of work into the code generator
503510
infrastructure, which allows us to implement more aggressive algorithms and
504511
make it run faster:</p>

llvm/include/llvm/ADT/BitVector.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ class BitVector {
311311
return !(*this == RHS);
312312
}
313313

314-
// Intersection, union, disjoint union.
314+
/// Intersection, union, disjoint union.
315315
BitVector &operator&=(const BitVector &RHS) {
316316
unsigned ThisWords = NumBitWords(size());
317317
unsigned RHSWords = NumBitWords(RHS.size());
@@ -328,7 +328,7 @@ class BitVector {
328328
return *this;
329329
}
330330

331-
// reset - Reset bits that are set in RHS. Same as *this &= ~RHS.
331+
/// reset - Reset bits that are set in RHS. Same as *this &= ~RHS.
332332
BitVector &reset(const BitVector &RHS) {
333333
unsigned ThisWords = NumBitWords(size());
334334
unsigned RHSWords = NumBitWords(RHS.size());
@@ -338,6 +338,23 @@ class BitVector {
338338
return *this;
339339
}
340340

341+
/// test - Check if (This - RHS) is zero.
342+
/// This is the same as reset(RHS) and any().
343+
bool test(const BitVector &RHS) const {
344+
unsigned ThisWords = NumBitWords(size());
345+
unsigned RHSWords = NumBitWords(RHS.size());
346+
unsigned i;
347+
for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
348+
if ((Bits[i] & ~RHS.Bits[i]) != 0)
349+
return true;
350+
351+
for (; i != ThisWords ; ++i)
352+
if (Bits[i] != 0)
353+
return true;
354+
355+
return false;
356+
}
357+
341358
BitVector &operator|=(const BitVector &RHS) {
342359
if (size() < RHS.size())
343360
resize(RHS.size());

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,10 @@ namespace ISD {
637637
ATOMIC_LOAD_UMIN,
638638
ATOMIC_LOAD_UMAX,
639639

640+
/// This corresponds to the llvm.lifetime.* intrinsics. The first operand
641+
/// is the chain and the second operand is the alloca pointer.
642+
LIFETIME_START, LIFETIME_END,
643+
640644
/// BUILTIN_OP_END - This must be the last enum value in this list.
641645
/// The target-specific pre-isel opcode values start here.
642646
BUILTIN_OP_END

llvm/include/llvm/CodeGen/MachineFrameInfo.h

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class MachineFunction;
2828
class MachineBasicBlock;
2929
class TargetFrameLowering;
3030
class BitVector;
31+
class Value;
3132

3233
/// The CalleeSavedInfo class tracks the information need to locate where a
3334
/// callee saved register is in the current frame.
@@ -103,14 +104,18 @@ class MachineFrameInfo {
103104
// protector.
104105
bool MayNeedSP;
105106

107+
/// Alloca - If this stack object is originated from an Alloca instruction
108+
/// this value saves the original IR allocation. Can be NULL.
109+
const Value *Alloca;
110+
106111
// PreAllocated - If true, the object was mapped into the local frame
107112
// block and doesn't need additional handling for allocation beyond that.
108113
bool PreAllocated;
109114

110115
StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM,
111-
bool isSS, bool NSP)
116+
bool isSS, bool NSP, const Value *Val)
112117
: SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM),
113-
isSpillSlot(isSS), MayNeedSP(NSP), PreAllocated(false) {}
118+
isSpillSlot(isSS), MayNeedSP(NSP), Alloca(Val), PreAllocated(false) {}
114119
};
115120

116121
/// Objects - The list of stack objects allocated...
@@ -362,6 +367,14 @@ class MachineFrameInfo {
362367
ensureMaxAlignment(Align);
363368
}
364369

370+
/// getObjectAllocation - Return the underlying Alloca of the specified
371+
/// stack object if it exists. Returns 0 if none exists.
372+
const Value* getObjectAllocation(int ObjectIdx) const {
373+
assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
374+
"Invalid Object Idx!");
375+
return Objects[ObjectIdx+NumFixedObjects].Alloca;
376+
}
377+
365378
/// NeedsStackProtector - Returns true if the object may need stack
366379
/// protectors.
367380
bool MayNeedStackProtector(int ObjectIdx) const {
@@ -482,9 +495,10 @@ class MachineFrameInfo {
482495
/// a nonnegative identifier to represent it.
483496
///
484497
int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS,
485-
bool MayNeedSP = false) {
498+
bool MayNeedSP = false, const Value *Alloca = 0) {
486499
assert(Size != 0 && "Cannot allocate zero size stack objects!");
487-
Objects.push_back(StackObject(Size, Alignment, 0, false, isSS, MayNeedSP));
500+
Objects.push_back(StackObject(Size, Alignment, 0, false, isSS, MayNeedSP,
501+
Alloca));
488502
int Index = (int)Objects.size() - NumFixedObjects - 1;
489503
assert(Index >= 0 && "Bad frame index!");
490504
ensureMaxAlignment(Alignment);
@@ -516,7 +530,7 @@ class MachineFrameInfo {
516530
///
517531
int CreateVariableSizedObject(unsigned Alignment) {
518532
HasVarSizedObjects = true;
519-
Objects.push_back(StackObject(0, Alignment, 0, false, false, true));
533+
Objects.push_back(StackObject(0, Alignment, 0, false, false, true, 0));
520534
ensureMaxAlignment(Alignment);
521535
return (int)Objects.size()-NumFixedObjects-1;
522536
}

llvm/include/llvm/CodeGen/Passes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,10 @@ namespace llvm {
404404
/// inserting cmov instructions.
405405
extern char &EarlyIfConverterID;
406406

407+
/// StackSlotColoring - This pass performs stack coloring and merging.
408+
/// It merges disjoint allocas to reduce the stack size.
409+
extern char &StackColoringID;
410+
407411
/// IfConverter - This pass performs machine code if conversion.
408412
extern char &IfConverterID;
409413

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ void initializeSinkingPass(PassRegistry&);
232232
void initializeSlotIndexesPass(PassRegistry&);
233233
void initializeSpillPlacementPass(PassRegistry&);
234234
void initializeStackProtectorPass(PassRegistry&);
235+
void initializeStackColoringPass(PassRegistry&);
235236
void initializeStackSlotColoringPass(PassRegistry&);
236237
void initializeStripDeadDebugInfoPass(PassRegistry&);
237238
void initializeStripDeadPrototypesPassPass(PassRegistry&);

llvm/include/llvm/Target/Target.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,18 @@ def BUNDLE : Instruction {
745745
let InOperandList = (ins variable_ops);
746746
let AsmString = "BUNDLE";
747747
}
748+
def LIFETIME_START : Instruction {
749+
let OutOperandList = (outs);
750+
let InOperandList = (ins i32imm:$id);
751+
let AsmString = "LIFETIME_START";
752+
let neverHasSideEffects = 1;
753+
}
754+
def LIFETIME_END : Instruction {
755+
let OutOperandList = (outs);
756+
let InOperandList = (ins i32imm:$id);
757+
let AsmString = "LIFETIME_END";
758+
let neverHasSideEffects = 1;
759+
}
748760
}
749761

750762
//===----------------------------------------------------------------------===//

llvm/include/llvm/Target/TargetOpcodes.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ namespace TargetOpcode {
8787
/// BUNDLE - This instruction represents an instruction bundle. Instructions
8888
/// which immediately follow a BUNDLE instruction which are marked with
8989
/// 'InsideBundle' flag are inside the bundle.
90-
BUNDLE
90+
BUNDLE = 14,
91+
92+
/// Lifetime markers.
93+
LIFETIME_START = 15,
94+
LIFETIME_END = 16
9195
};
9296
} // end namespace TargetOpcode
9397
} // end namespace llvm

llvm/lib/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ add_llvm_library(LLVMCodeGen
9595
SplitKit.cpp
9696
StackProtector.cpp
9797
StackSlotColoring.cpp
98+
StackColoring.cpp
9899
StrongPHIElimination.cpp
99100
TailDuplication.cpp
100101
TargetFrameLoweringImpl.cpp

llvm/lib/CodeGen/CodeGen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
5656
initializeRegisterCoalescerPass(Registry);
5757
initializeSlotIndexesPass(Registry);
5858
initializeStackProtectorPass(Registry);
59+
initializeStackColoringPass(Registry);
5960
initializeStackSlotColoringPass(Registry);
6061
initializeStrongPHIEliminationPass(Registry);
6162
initializeTailDuplicatePassPass(Registry);

0 commit comments

Comments
 (0)