Skip to content

Commit 147851e

Browse files
committed
BitcodeReader: Change mechanics of BlockAddress forward references, NFC
Now that we can reliably handle forward references to `BlockAddress` (r214563), change the mechanics to simplify predicting use-list order. Previously, we created dummy `GlobalVariable`s to represent block addresses. After every function was materialized, we'd go through any forward references to its blocks and RAUW them with a proper `BlockAddress` constant. This causes some (potentially a lot of) unnecessary use-list churn, since any constant expression that it's a part of will need to be rematerialized as well. Instead, pre-construct a `BasicBlock` immediately -- without attaching it to its (empty) `Function` -- and use that to construct a `BlockAddress`. This constant will not have to be regenerated. When the function body is parsed, hook this pre-constructed basic block up in the right place using `BasicBlock::insertInto()`. Both before and after this change, the IR is temporarily in an invalid state that gets resolved when `materializeForwardReferencedFunctions()` gets called. This is a prep commit that's part of PR5680, but the only functionality change is the reduction of churn in the constant pool. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@214570 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 7e59545 commit 147851e

File tree

2 files changed

+51
-38
lines changed

2 files changed

+51
-38
lines changed

lib/Bitcode/Reader/BitcodeReader.cpp

+47-34
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ std::error_code BitcodeReader::materializeForwardReferencedFunctions() {
3838
// Prevent recursion.
3939
WillMaterializeAllForwardRefs = true;
4040

41-
while (!BlockAddrFwdRefs.empty()) {
42-
Function *F = BlockAddrFwdRefs.begin()->first;
41+
while (!BasicBlockFwdRefs.empty()) {
42+
Function *F = BasicBlockFwdRefs.begin()->first;
4343
assert(F && "Expected valid function");
4444
// Check for a function that isn't materializable to prevent an infinite
4545
// loop. When parsing a blockaddress stored in a global variable, there
@@ -71,7 +71,7 @@ void BitcodeReader::FreeState() {
7171
DeferredFunctionInfo.clear();
7272
MDKindMap.clear();
7373

74-
assert(BlockAddrFwdRefs.empty() && "Unresolved blockaddress fwd references");
74+
assert(BasicBlockFwdRefs.empty() && "Unresolved blockaddress fwd references");
7575
}
7676

7777
//===----------------------------------------------------------------------===//
@@ -1612,24 +1612,26 @@ std::error_code BitcodeReader::ParseConstants() {
16121612

16131613
// If the function is already parsed we can insert the block address right
16141614
// away.
1615+
BasicBlock *BB;
1616+
unsigned BBID = Record[2];
1617+
if (!BBID)
1618+
// Invalid reference to entry block.
1619+
return Error(BitcodeError::InvalidID);
16151620
if (!Fn->empty()) {
16161621
Function::iterator BBI = Fn->begin(), BBE = Fn->end();
1617-
for (size_t I = 0, E = Record[2]; I != E; ++I) {
1622+
for (size_t I = 0, E = BBID; I != E; ++I) {
16181623
if (BBI == BBE)
16191624
return Error(BitcodeError::InvalidID);
16201625
++BBI;
16211626
}
1622-
V = BlockAddress::get(Fn, BBI);
1627+
BB = BBI;
16231628
} else {
16241629
// Otherwise insert a placeholder and remember it so it can be inserted
16251630
// when the function is parsed.
1626-
GlobalVariable *FwdRef = new GlobalVariable(*Fn->getParent(),
1627-
Type::getInt8Ty(Context),
1628-
false, GlobalValue::InternalLinkage,
1629-
nullptr, "");
1630-
BlockAddrFwdRefs[Fn].push_back(std::make_pair(Record[2], FwdRef));
1631-
V = FwdRef;
1631+
BB = BasicBlock::Create(Context);
1632+
BasicBlockFwdRefs[Fn].emplace_back(BBID, BB);
16321633
}
1634+
V = BlockAddress::get(Fn, BB);
16331635
break;
16341636
}
16351637
}
@@ -2367,15 +2369,45 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
23672369
switch (BitCode) {
23682370
default: // Default behavior: reject
23692371
return Error(BitcodeError::InvalidValue);
2370-
case bitc::FUNC_CODE_DECLAREBLOCKS: // DECLAREBLOCKS: [nblocks]
2372+
case bitc::FUNC_CODE_DECLAREBLOCKS: { // DECLAREBLOCKS: [nblocks]
23712373
if (Record.size() < 1 || Record[0] == 0)
23722374
return Error(BitcodeError::InvalidRecord);
23732375
// Create all the basic blocks for the function.
23742376
FunctionBBs.resize(Record[0]);
2375-
for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i)
2376-
FunctionBBs[i] = BasicBlock::Create(Context, "", F);
2377+
2378+
// See if anything took the address of blocks in this function.
2379+
auto BBFRI = BasicBlockFwdRefs.find(F);
2380+
if (BBFRI == BasicBlockFwdRefs.end()) {
2381+
for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i)
2382+
FunctionBBs[i] = BasicBlock::Create(Context, "", F);
2383+
} else {
2384+
auto &BBRefs = BBFRI->second;
2385+
std::sort(BBRefs.begin(), BBRefs.end(),
2386+
[](const std::pair<unsigned, BasicBlock *> &LHS,
2387+
const std::pair<unsigned, BasicBlock *> &RHS) {
2388+
return LHS.first < RHS.first;
2389+
});
2390+
unsigned R = 0, RE = BBRefs.size();
2391+
for (unsigned I = 0, E = FunctionBBs.size(); I != E; ++I)
2392+
if (R != RE && BBRefs[R].first == I) {
2393+
assert(I != 0 && "Invalid reference to entry block");
2394+
BasicBlock *BB = BBRefs[R++].second;
2395+
BB->insertInto(F);
2396+
FunctionBBs[I] = BB;
2397+
} else {
2398+
FunctionBBs[I] = BasicBlock::Create(Context, "", F);
2399+
}
2400+
// Check for invalid basic block references.
2401+
if (R != RE)
2402+
return Error(BitcodeError::InvalidID);
2403+
2404+
// Erase from the table.
2405+
BasicBlockFwdRefs.erase(BBFRI);
2406+
}
2407+
23772408
CurBB = FunctionBBs[0];
23782409
continue;
2410+
}
23792411

23802412
case bitc::FUNC_CODE_DEBUG_LOC_AGAIN: // DEBUG_LOC_AGAIN
23812413
// This record indicates that the last instruction is at the same
@@ -3210,25 +3242,6 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
32103242
// FIXME: Check for unresolved forward-declared metadata references
32113243
// and clean up leaks.
32123244

3213-
// See if anything took the address of blocks in this function. If so,
3214-
// resolve them now.
3215-
DenseMap<Function*, std::vector<BlockAddrRefTy> >::iterator BAFRI =
3216-
BlockAddrFwdRefs.find(F);
3217-
if (BAFRI != BlockAddrFwdRefs.end()) {
3218-
std::vector<BlockAddrRefTy> &RefList = BAFRI->second;
3219-
for (unsigned i = 0, e = RefList.size(); i != e; ++i) {
3220-
unsigned BlockIdx = RefList[i].first;
3221-
if (BlockIdx >= FunctionBBs.size())
3222-
return Error(BitcodeError::InvalidID);
3223-
3224-
GlobalVariable *FwdRef = RefList[i].second;
3225-
FwdRef->replaceAllUsesWith(BlockAddress::get(F, FunctionBBs[BlockIdx]));
3226-
FwdRef->eraseFromParent();
3227-
}
3228-
3229-
BlockAddrFwdRefs.erase(BAFRI);
3230-
}
3231-
32323245
// Trim the value list down to the size it was before we parsed this function.
32333246
ValueList.shrinkTo(ModuleValueListSize);
32343247
MDValueList.shrinkTo(ModuleMDValueListSize);
@@ -3351,7 +3364,7 @@ std::error_code BitcodeReader::MaterializeModule(Module *M) {
33513364

33523365
// Check that all block address forward references got resolved (as we
33533366
// promised above).
3354-
if (!BlockAddrFwdRefs.empty())
3367+
if (!BasicBlockFwdRefs.empty())
33553368
return Error(BitcodeError::NeverResolvedFunctionFromBlockAddress);
33563369

33573370
// Upgrade any intrinsic calls that slipped through (should not happen!) and

lib/Bitcode/Reader/BitcodeReader.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,10 @@ class BitcodeReader : public GVMaterializer {
179179
/// stream.
180180
DenseMap<Function*, uint64_t> DeferredFunctionInfo;
181181

182-
/// BlockAddrFwdRefs - These are blockaddr references to basic blocks. These
183-
/// are resolved lazily when functions are loaded.
184-
typedef std::pair<unsigned, GlobalVariable*> BlockAddrRefTy;
185-
DenseMap<Function*, std::vector<BlockAddrRefTy> > BlockAddrFwdRefs;
182+
/// These are basic blocks forward-referenced by block addresses. They are
183+
/// inserted lazily into functions when they're loaded.
184+
typedef std::pair<unsigned, BasicBlock *> BasicBlockRefTy;
185+
DenseMap<Function *, std::vector<BasicBlockRefTy>> BasicBlockFwdRefs;
186186

187187
/// UseRelativeIDs - Indicates that we are using a new encoding for
188188
/// instruction operands where most operands in the current

0 commit comments

Comments
 (0)