Skip to content
This repository has been archived by the owner on Jan 1, 2023. It is now read-only.

Commit

Permalink
[CodeExtractor] Simplify findAllocas, NFC
Browse files Browse the repository at this point in the history
Split getLifetimeMarkers out into its own method and have it return a
struct.

Differential Revision: https://reviews.llvm.org/D64467

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365659 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
vedantk committed Jul 10, 2019
1 parent fd3a33d commit 9d3ff8e
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 73 deletions.
10 changes: 10 additions & 0 deletions include/llvm/Transforms/Utils/CodeExtractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,16 @@ class Value;
BasicBlock *findOrCreateBlockForHoisting(BasicBlock *CommonExitBlock);

private:
struct LifetimeMarkerInfo {
bool SinkLifeStart = false;
bool HoistLifeEnd = false;
Instruction *LifeStart = nullptr;
Instruction *LifeEnd = nullptr;
};

LifetimeMarkerInfo getLifetimeMarkers(Instruction *Addr,
BasicBlock *ExitBlock) const;

void severSplitPHINodesOfEntry(BasicBlock *&Header);
void severSplitPHINodesOfExits(const SmallPtrSetImpl<BasicBlock *> &Exits);
void splitReturnBlocks();
Expand Down
164 changes: 91 additions & 73 deletions lib/Transforms/Utils/CodeExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,11 +410,74 @@ CodeExtractor::findOrCreateBlockForHoisting(BasicBlock *CommonExitBlock) {
return CommonExitBlock;
}

// Find the pair of life time markers for address 'Addr' that are either
// defined inside the outline region or can legally be shrinkwrapped into the
// outline region. If there are not other untracked uses of the address, return
// the pair of markers if found; otherwise return a pair of nullptr.
CodeExtractor::LifetimeMarkerInfo
CodeExtractor::getLifetimeMarkers(Instruction *Addr,
BasicBlock *ExitBlock) const {
LifetimeMarkerInfo Info;

for (User *U : Addr->users()) {
IntrinsicInst *IntrInst = dyn_cast<IntrinsicInst>(U);
if (IntrInst) {
if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start) {
// Do not handle the case where Addr has multiple start markers.
if (Info.LifeStart)
return {};
Info.LifeStart = IntrInst;
}
if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_end) {
if (Info.LifeEnd)
return {};
Info.LifeEnd = IntrInst;
}
continue;
}
// Find untracked uses of the address, bail.
if (!definedInRegion(Blocks, U))
return {};
}

if (!Info.LifeStart || !Info.LifeEnd)
return {};

Info.SinkLifeStart = !definedInRegion(Blocks, Info.LifeStart);
Info.HoistLifeEnd = !definedInRegion(Blocks, Info.LifeEnd);
// Do legality check.
if ((Info.SinkLifeStart || Info.HoistLifeEnd) &&
!isLegalToShrinkwrapLifetimeMarkers(Addr))
return {};

// Check to see if we have a place to do hoisting, if not, bail.
if (Info.HoistLifeEnd && !ExitBlock)
return {};

return Info;
}

void CodeExtractor::findAllocas(ValueSet &SinkCands, ValueSet &HoistCands,
BasicBlock *&ExitBlock) const {
Function *Func = (*Blocks.begin())->getParent();
ExitBlock = getCommonExitBlock(Blocks);

auto moveOrIgnoreLifetimeMarkers =
[&](const LifetimeMarkerInfo &LMI) -> bool {
if (!LMI.LifeStart)
return false;
if (LMI.SinkLifeStart) {
LLVM_DEBUG(dbgs() << "Sinking lifetime.start: " << *LMI.LifeStart
<< "\n");
SinkCands.insert(LMI.LifeStart);
}
if (LMI.HoistLifeEnd) {
LLVM_DEBUG(dbgs() << "Hoisting lifetime.end: " << *LMI.LifeEnd << "\n");
HoistCands.insert(LMI.LifeEnd);
}
return true;
};

for (BasicBlock &BB : *Func) {
if (Blocks.count(&BB))
continue;
Expand All @@ -423,96 +486,51 @@ void CodeExtractor::findAllocas(ValueSet &SinkCands, ValueSet &HoistCands,
if (!AI)
continue;

// Find the pair of life time markers for address 'Addr' that are either
// defined inside the outline region or can legally be shrinkwrapped into
// the outline region. If there are not other untracked uses of the
// address, return the pair of markers if found; otherwise return a pair
// of nullptr.
auto GetLifeTimeMarkers =
[&](Instruction *Addr, bool &SinkLifeStart,
bool &HoistLifeEnd) -> std::pair<Instruction *, Instruction *> {
Instruction *LifeStart = nullptr, *LifeEnd = nullptr;

for (User *U : Addr->users()) {
IntrinsicInst *IntrInst = dyn_cast<IntrinsicInst>(U);
if (IntrInst) {
if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start) {
// Do not handle the case where AI has multiple start markers.
if (LifeStart)
return std::make_pair<Instruction *>(nullptr, nullptr);
LifeStart = IntrInst;
}
if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_end) {
if (LifeEnd)
return std::make_pair<Instruction *>(nullptr, nullptr);
LifeEnd = IntrInst;
}
continue;
}
// Find untracked uses of the address, bail.
if (!definedInRegion(Blocks, U))
return std::make_pair<Instruction *>(nullptr, nullptr);
}

if (!LifeStart || !LifeEnd)
return std::make_pair<Instruction *>(nullptr, nullptr);

SinkLifeStart = !definedInRegion(Blocks, LifeStart);
HoistLifeEnd = !definedInRegion(Blocks, LifeEnd);
// Do legality Check.
if ((SinkLifeStart || HoistLifeEnd) &&
!isLegalToShrinkwrapLifetimeMarkers(Addr))
return std::make_pair<Instruction *>(nullptr, nullptr);

// Check to see if we have a place to do hoisting, if not, bail.
if (HoistLifeEnd && !ExitBlock)
return std::make_pair<Instruction *>(nullptr, nullptr);

return std::make_pair(LifeStart, LifeEnd);
};

bool SinkLifeStart = false, HoistLifeEnd = false;
auto Markers = GetLifeTimeMarkers(AI, SinkLifeStart, HoistLifeEnd);

if (Markers.first) {
if (SinkLifeStart)
SinkCands.insert(Markers.first);
LifetimeMarkerInfo MarkerInfo = getLifetimeMarkers(AI, ExitBlock);
bool Moved = moveOrIgnoreLifetimeMarkers(MarkerInfo);
if (Moved) {
LLVM_DEBUG(dbgs() << "Sinking alloca: " << *AI << "\n");
SinkCands.insert(AI);
if (HoistLifeEnd)
HoistCands.insert(Markers.second);
continue;
}

// Follow the bitcast.
Instruction *MarkerAddr = nullptr;
// Follow any bitcasts.
SmallVector<Instruction *, 2> Bitcasts;
SmallVector<LifetimeMarkerInfo, 2> BitcastLifetimeInfo;
for (User *U : AI->users()) {
if (U->stripInBoundsConstantOffsets() == AI) {
SinkLifeStart = false;
HoistLifeEnd = false;
Instruction *Bitcast = cast<Instruction>(U);
Markers = GetLifeTimeMarkers(Bitcast, SinkLifeStart, HoistLifeEnd);
if (Markers.first) {
MarkerAddr = Bitcast;
LifetimeMarkerInfo LMI = getLifetimeMarkers(Bitcast, ExitBlock);
if (LMI.LifeStart) {
Bitcasts.push_back(Bitcast);
BitcastLifetimeInfo.push_back(LMI);
continue;
}
}

// Found unknown use of AI.
if (!definedInRegion(Blocks, U)) {
MarkerAddr = nullptr;
Bitcasts.clear();
break;
}
}

if (MarkerAddr) {
if (SinkLifeStart)
SinkCands.insert(Markers.first);
if (!definedInRegion(Blocks, MarkerAddr))
SinkCands.insert(MarkerAddr);
SinkCands.insert(AI);
if (HoistLifeEnd)
HoistCands.insert(Markers.second);
// Either no bitcasts reference the alloca or there are unknown uses.
if (Bitcasts.empty())
continue;

Instruction *BitcastAddr = Bitcasts.back();
const LifetimeMarkerInfo &LMI = BitcastLifetimeInfo.back();
assert(LMI.LifeStart &&
"Unsafe to sink bitcast without lifetime markers");
moveOrIgnoreLifetimeMarkers(LMI);
if (!definedInRegion(Blocks, BitcastAddr)) {
LLVM_DEBUG(dbgs() << "Sinking bitcast-of-alloca: " << *BitcastAddr
<< "\n");
SinkCands.insert(BitcastAddr);
}
LLVM_DEBUG(dbgs() << "Sinking alloca (via bitcast): " << *AI << "\n");
SinkCands.insert(AI);
}
}
}
Expand Down Expand Up @@ -1412,7 +1430,7 @@ Function *CodeExtractor::extractCodeRegion() {
// Find inputs to, outputs from the code region.
findInputsOutputs(inputs, outputs, SinkingCands);

// Now sink all instructions which only have non-phi uses inside the region
// Now sink all instructions which only have non-phi uses inside the region.
for (auto *II : SinkingCands)
cast<Instruction>(II)->moveBefore(*newFuncRoot,
newFuncRoot->getFirstInsertionPt());
Expand Down

0 comments on commit 9d3ff8e

Please sign in to comment.