76 changes: 39 additions & 37 deletions llvm/lib/CodeGen/SafeStackColoring.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <utility>
Expand All @@ -39,6 +40,9 @@ class StackColoring {
/// Each bit in the BitVector represents the liveness property
/// for a different stack slot.
struct BlockLifetimeInfo {
explicit BlockLifetimeInfo(unsigned Size)
: Begin(Size), End(Size), LiveIn(Size), LiveOut(Size) {}

/// Which slots BEGINs in each basic block.
BitVector Begin;

Expand All @@ -55,107 +59,105 @@ class StackColoring {
public:
/// This class represents a set of interesting instructions where an alloca is
/// live.
struct LiveRange {
BitVector bv;
class LiveRange {
BitVector Bits;
friend raw_ostream &operator<<(raw_ostream &OS,
const StackColoring::LiveRange &R);

void SetMaximum(int size) { bv.resize(size); }
void AddRange(unsigned start, unsigned end) { bv.set(start, end); }
public:
LiveRange(unsigned Size, bool Set = false) : Bits(Size, Set) {}
void addRange(unsigned Start, unsigned End) { Bits.set(Start, End); }

bool Overlaps(const LiveRange &Other) const {
return bv.anyCommon(Other.bv);
bool overlaps(const LiveRange &Other) const {
return Bits.anyCommon(Other.Bits);
}

void Join(const LiveRange &Other) { bv |= Other.bv; }
void join(const LiveRange &Other) { Bits |= Other.Bits; }
};

private:
Function &F;
const Function &F;

/// Maps active slots (per bit) for each basic block.
using LivenessMap = DenseMap<BasicBlock *, BlockLifetimeInfo>;
using LivenessMap = DenseMap<const BasicBlock *, BlockLifetimeInfo>;
LivenessMap BlockLiveness;

/// Number of interesting instructions.
int NumInst = -1;

/// Numeric ids for interesting instructions.
DenseMap<Instruction *, unsigned> InstructionNumbering;
DenseMap<const IntrinsicInst *, unsigned> InstructionNumbering;

/// A range [Start, End) of instruction ids for each basic block.
/// Instructions inside each BB have monotonic and consecutive ids.
DenseMap<const BasicBlock *, std::pair<unsigned, unsigned>> BlockInstRange;

ArrayRef<AllocaInst *> Allocas;
ArrayRef<const AllocaInst *> Allocas;
unsigned NumAllocas;
DenseMap<AllocaInst *, unsigned> AllocaNumbering;
DenseMap<const AllocaInst *, unsigned> AllocaNumbering;

/// LiveRange for allocas.
SmallVector<LiveRange, 8> LiveRanges;

/// The set of allocas that have at least one lifetime.start. All other
/// allocas get LiveRange that corresponds to the entire function.
BitVector InterestingAllocas;
SmallVector<Instruction *, 8> Markers;

struct Marker {
unsigned AllocaNo;
bool IsStart;
};

/// List of {InstNo, {AllocaNo, IsStart}} for each BB, ordered by InstNo.
DenseMap<BasicBlock *, SmallVector<std::pair<unsigned, Marker>, 4>> BBMarkers;
DenseMap<const BasicBlock *, SmallVector<std::pair<unsigned, Marker>, 4>>
BBMarkers;

void dumpAllocas();
void dumpBlockLiveness();
void dumpLiveRanges();
void dumpAllocas() const;
void dumpBlockLiveness() const;
void dumpLiveRanges() const;

bool readMarker(Instruction *I, bool *IsStart);
void collectMarkers();
void calculateLocalLiveness();
void calculateLiveIntervals();

public:
StackColoring(Function &F, ArrayRef<AllocaInst *> Allocas)
: F(F), Allocas(Allocas), NumAllocas(Allocas.size()) {}
StackColoring(const Function &F, ArrayRef<const AllocaInst *> Allocas);

void run();
void removeAllMarkers();
std::vector<const IntrinsicInst *> getMarkers() const;

/// Returns a set of "interesting" instructions where the given alloca is
/// live. Not all instructions in a function are interesting: we pick a set
/// that is large enough for LiveRange::Overlaps to be correct.
const LiveRange &getLiveRange(AllocaInst *AI);
const LiveRange &getLiveRange(const AllocaInst *AI) const;

/// Returns a live range that represents an alloca that is live throughout the
/// entire function.
LiveRange getFullLiveRange() {
LiveRange getFullLiveRange() const {
assert(NumInst >= 0);
LiveRange R;
R.SetMaximum(NumInst);
R.AddRange(0, NumInst);
return R;
return LiveRange(NumInst, true);
}
};

static inline raw_ostream &operator<<(raw_ostream &OS, const BitVector &V) {
OS << "{";
int idx = V.find_first();
bool first = true;
while (idx >= 0) {
if (!first) {
int Idx = V.find_first();
bool First = true;
while (Idx >= 0) {
if (!First) {
OS << ", ";
}
first = false;
OS << idx;
idx = V.find_next(idx);
First = false;
OS << Idx;
Idx = V.find_next(Idx);
}
OS << "}";
return OS;
}

static inline raw_ostream &operator<<(raw_ostream &OS,
const StackColoring::LiveRange &R) {
return OS << R.bv;
inline raw_ostream &operator<<(raw_ostream &OS,
const StackColoring::LiveRange &R) {
return OS << R.Bits;
}

} // end namespace safestack
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/CodeGen/SafeStackLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void StackLayout::layoutObject(StackObject &Obj) {
LLVM_DEBUG(dbgs() << " Does not intersect, skip.\n");
continue;
}
if (Obj.Range.Overlaps(R.Range)) {
if (Obj.Range.overlaps(R.Range)) {
// Find the next appropriate location.
Start = AdjustStackOffset(R.End, Obj.Size, Obj.Alignment);
End = Start + Obj.Size;
Expand All @@ -95,7 +95,7 @@ void StackLayout::layoutObject(StackObject &Obj) {
if (Start > LastRegionEnd) {
LLVM_DEBUG(dbgs() << " Creating gap region: " << LastRegionEnd << " .. "
<< Start << "\n");
Regions.emplace_back(LastRegionEnd, Start, StackColoring::LiveRange());
Regions.emplace_back(LastRegionEnd, Start, StackColoring::LiveRange(0));
LastRegionEnd = Start;
}
LLVM_DEBUG(dbgs() << " Creating new region: " << LastRegionEnd << " .. "
Expand Down Expand Up @@ -124,7 +124,7 @@ void StackLayout::layoutObject(StackObject &Obj) {
// Update live ranges for all affected regions.
for (StackRegion &R : Regions) {
if (Start < R.End && End > R.Start)
R.Range.Join(Obj.Range);
R.Range.join(Obj.Range);
if (End <= R.End)
break;
}
Expand Down