Skip to content

Commit

Permalink
Gate our extensions to the llvm block map.
Browse files Browse the repository at this point in the history
This allows us to use upstream's test unchanged.
  • Loading branch information
vext01 committed Nov 28, 2022
1 parent 42490d3 commit c75eec9
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 136 deletions.
248 changes: 128 additions & 120 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ static cl::opt<bool>
"optimisations and transformations have run."));

extern bool YkAllocLLVMBBAddrMapSection;
extern bool YkExtendedLLVMBBAddrMapSection;

const char DWARFGroupName[] = "dwarf";
const char DWARFGroupDescription[] = "DWARF Emission";
Expand Down Expand Up @@ -1438,141 +1439,147 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
emitLabelDifferenceAsULEB128(MBB.getEndSymbol(), MBBSymbol);
OutStreamer->emitULEB128IntValue(getBBAddrMapMetadata(MBB));
PrevMBBEndSymbol = MBB.getEndSymbol();
// Find BBs corresponding with this MBB as described above.
const BasicBlock *CorrBB = MBB.getBasicBlock();
std::vector<const BasicBlock *> CorrBBs;
while (CorrBB != nullptr) {
CorrBBs.push_back(CorrBB);
const Instruction *Term = CorrBB->getTerminator();
assert(Term != nullptr);
if ((isa<BranchInst>(Term)) &&
(!(dyn_cast<const BranchInst>(Term))->isConditional())) {
CorrBB = CorrBB->getUniqueSuccessor();
assert(CorrBB != nullptr);
if (MergedBBs.count(CorrBB) == 0) {

if (YkExtendedLLVMBBAddrMapSection) {
// Find BBs corresponding with this MBB as described above.
const BasicBlock *CorrBB = MBB.getBasicBlock();
std::vector<const BasicBlock *> CorrBBs;
while (CorrBB != nullptr) {
CorrBBs.push_back(CorrBB);
const Instruction *Term = CorrBB->getTerminator();
assert(Term != nullptr);
if ((isa<BranchInst>(Term)) &&
(!(dyn_cast<const BranchInst>(Term))->isConditional())) {
CorrBB = CorrBB->getUniqueSuccessor();
assert(CorrBB != nullptr);
if (MergedBBs.count(CorrBB) == 0) {
CorrBB = nullptr;
}
} else {
CorrBB = nullptr;
}
} else {
CorrBB = nullptr;
}
}
// Emit the number of corresponding BasicBlocks.
OutStreamer->emitULEB128IntValue(CorrBBs.size());
// Emit the corresponding block indices.
for (auto CorrBB : CorrBBs) {
size_t I = 0;
bool Found = false;
for (auto It = F.begin(); It != F.end(); It++) {
const BasicBlock *BB = &*It;
if (BB == CorrBB) {
Found = true;
break;
// Emit the number of corresponding BasicBlocks.
OutStreamer->emitULEB128IntValue(CorrBBs.size());
// Emit the corresponding block indices.
for (auto CorrBB : CorrBBs) {
size_t I = 0;
bool Found = false;
for (auto It = F.begin(); It != F.end(); It++) {
const BasicBlock *BB = &*It;
if (BB == CorrBB) {
Found = true;
break;
}
I++;
}
I++;
if (!Found)
OutContext.reportError(SMLoc(), "Couldn't find the block's index");
OutStreamer->emitULEB128IntValue(I);
}
if (!Found)
OutContext.reportError(SMLoc(), "Couldn't find the block's index");
OutStreamer->emitULEB128IntValue(I);
}

// Emit call marker table for the Yk JIT.
//
// The table is a size header, followed by call instruction addresses.
//
// YKOPT: to save space, instead of using absolute symbol addresses, compute
// the distance from the start of the block and use uleb128 encoding.
const size_t NumCalls = YkCallMarkerSyms[&MBB].size();
OutStreamer->emitULEB128IntValue(NumCalls);
for (auto Tup : YkCallMarkerSyms[&MBB]) {
// Emit address of the call instruction.
OutStreamer->emitSymbolValue(std::get<0>(Tup), getPointerSize());
// Emit address of target if known, or 0.
MCSymbol *Target = std::get<1>(Tup);
if (Target)
OutStreamer->emitSymbolValue(Target, getPointerSize());
else
OutStreamer->emitIntValue(0, getPointerSize());
}
// Emit call marker table for the Yk JIT.
//
// The table is a size header, followed by call instruction addresses.
//
// YKOPT: to save space, instead of using absolute symbol addresses,
// compute the distance from the start of the block and use uleb128
// encoding.
const size_t NumCalls = YkCallMarkerSyms[&MBB].size();
OutStreamer->emitULEB128IntValue(NumCalls);
for (auto Tup : YkCallMarkerSyms[&MBB]) {
// Emit address of the call instruction.
OutStreamer->emitSymbolValue(std::get<0>(Tup), getPointerSize());
// Emit address of target if known, or 0.
MCSymbol *Target = std::get<1>(Tup);
if (Target)
OutStreamer->emitSymbolValue(Target, getPointerSize());
else
OutStreamer->emitIntValue(0, getPointerSize());
}

// Emit successor information.
//
// Each codegenned block gets a record indicating any statically known
// successors. The record starts with a `SuccessorKind` byte:
enum SuccessorKind {
// One successor.
Unconditional = 0,
// Choice of two successors.
Conditional = 1,
// A control flow edge known only at runtime, e.g. a return or an indirect
// branch.
Dynamic = 2,
};

// Then depending of the `SuccessorKind` there is a payload describing the
// successors:
//
// `Unconditional`: [target-address: u64]
// `Conditional`: [taken-address: u64, not-taken-address: u64]
// `Dynamic`: [] (i.e. nothing, because nothing is statically known)

MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
SmallVector<MachineOperand> Conds;

if (!TI->analyzeBranch(const_cast<MachineBasicBlock &>(MBB), TBB, FBB,
Conds)) {
// The block ends with a branch or a fall-thru.
if (!TBB && !FBB) {
// Both null: block has no terminator and either falls through or
// diverges.
OutStreamer->emitInt8(Unconditional);
MachineBasicBlock *ThruBB = findFallthruBlock(&MBB);
if (ThruBB) {
OutStreamer->emitSymbolValue(BBSym(ThruBB, FunctionSymbol),
getPointerSize());
} else {
OutStreamer->emitInt64(0); // Divergent.
}
} else if (TBB && !FBB) {
// Only FBB null: block either ends with an unconditional branch or a
// conditional branch whose false arm falls through or diverges.
if (Conds.empty()) {
// No conditions: unconditional branch.
// Emit successor information.
//
// Each codegenned block gets a record indicating any statically known
// successors. The record starts with a `SuccessorKind` byte:
enum SuccessorKind {
// One successor.
Unconditional = 0,
// Choice of two successors.
Conditional = 1,
// A control flow edge known only at runtime, e.g. a return or an
// indirect
// branch.
Dynamic = 2,
};

// Then depending of the `SuccessorKind` there is a payload describing the
// successors:
//
// `Unconditional`: [target-address: u64]
// `Conditional`: [taken-address: u64, not-taken-address: u64]
// `Dynamic`: [] (i.e. nothing, because nothing is statically known)

MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
SmallVector<MachineOperand> Conds;

if (!TI->analyzeBranch(const_cast<MachineBasicBlock &>(MBB), TBB, FBB,
Conds)) {
// The block ends with a branch or a fall-thru.
if (!TBB && !FBB) {
// Both null: block has no terminator and either falls through or
// diverges.
OutStreamer->emitInt8(Unconditional);
OutStreamer->emitSymbolValue(BBSym(TBB, FunctionSymbol),
getPointerSize());
} else {
// Has conditions: conditional branch followed by fallthru or
// divergence.
MachineBasicBlock *ThruBB = findFallthruBlock(&MBB);
OutStreamer->emitInt8(Conditional);
OutStreamer->emitSymbolValue(BBSym(TBB, FunctionSymbol),
getPointerSize());
if (ThruBB) {
OutStreamer->emitSymbolValue(BBSym(ThruBB, FunctionSymbol),
getPointerSize());
} else {
OutStreamer->emitInt64(0); // Divergent.
}
} else if (TBB && !FBB) {
// Only FBB null: block either ends with an unconditional branch or a
// conditional branch whose false arm falls through or diverges.
if (Conds.empty()) {
// No conditions: unconditional branch.
OutStreamer->emitInt8(Unconditional);
OutStreamer->emitSymbolValue(BBSym(TBB, FunctionSymbol),
getPointerSize());
} else {
// Has conditions: conditional branch followed by fallthru or
// divergence.
MachineBasicBlock *ThruBB = findFallthruBlock(&MBB);
OutStreamer->emitInt8(Conditional);
OutStreamer->emitSymbolValue(BBSym(TBB, FunctionSymbol),
getPointerSize());
if (ThruBB) {
OutStreamer->emitSymbolValue(BBSym(ThruBB, FunctionSymbol),
getPointerSize());
} else {
OutStreamer->emitInt64(0); // Divergent.
}
}
} else {
// Conditional branch followed by an unconditional branch.
assert(TBB && FBB);
OutStreamer->emitInt8(Conditional);
OutStreamer->emitSymbolValue(BBSym(TBB, FunctionSymbol),
getPointerSize());
OutStreamer->emitSymbolValue(BBSym(FBB, FunctionSymbol),
getPointerSize());
}
} else {
// Conditional branch followed by an unconditional branch.
assert(TBB && FBB);
OutStreamer->emitInt8(Conditional);
OutStreamer->emitSymbolValue(BBSym(TBB, FunctionSymbol),
getPointerSize());
OutStreamer->emitSymbolValue(BBSym(FBB, FunctionSymbol),
getPointerSize());
}
} else {
// Wasn't a branch or a fall-thru. Must be a different kind of terminator.
const MachineInstr *LastI = &*MBB.instr_rbegin();
if (LastI->isReturn() || LastI->isIndirectBranch()) {
OutStreamer->emitInt8(Dynamic);
} else {
std::string Msg = "unhandled block terminator in block: ";
raw_string_ostream OS(Msg);
LastI->print(OS);
OutContext.reportError(SMLoc(), Msg);
// Wasn't a branch or a fall-thru. Must be a different kind of
// terminator.
const MachineInstr *LastI = &*MBB.instr_rbegin();
if (LastI->isReturn() || LastI->isIndirectBranch()) {
OutStreamer->emitInt8(Dynamic);
} else {
std::string Msg = "unhandled block terminator in block: ";
raw_string_ostream OS(Msg);
LastI->print(OS);
OutContext.reportError(SMLoc(), Msg);
}
}
}
}
Expand Down Expand Up @@ -1697,7 +1704,8 @@ void AsmPrinter::emitFunctionBody() {
// Print a label for the basic block.
emitBasicBlockStart(MBB);

YkCallMarkerSyms.insert({&MBB, {}});
if (YkExtendedLLVMBBAddrMapSection)
YkCallMarkerSyms.insert({&MBB, {}});

DenseMap<StringRef, unsigned> MnemonicCounts;
for (auto &MI : MBB) {
Expand Down Expand Up @@ -1774,7 +1782,7 @@ void AsmPrinter::emitFunctionBody() {
break;
default:

if (YkAllocLLVMBBAddrMapSection && MI.isCall() &&
if (YkExtendedLLVMBBAddrMapSection && MI.isCall() &&
(MI.getOpcode() != TargetOpcode::STACKMAP) &&
(MI.getOpcode() != TargetOpcode::PATCHPOINT) &&
(MI.getOpcode() != TargetOpcode::STATEPOINT)) {
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Support/Yk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ static cl::opt<bool, true> YkAllocLLVMBBAddrMapSectionParser(
"yk-alloc-llvmbbaddrmap-section",
cl::desc("Make the `.llvmbbaddrmap` section loadable"), cl::NotHidden,
cl::location(YkAllocLLVMBBAddrMapSection));

bool YkExtendedLLVMBBAddrMapSection;
static cl::opt<bool, true> YkExtendedLLVMBBAddrMapSectionParser(
"yk-extended-llvmbbaddrmap-section",
cl::desc("Use the extended Yk `.llvmbbaddrmap` section format"),
cl::NotHidden, cl::location(YkExtendedLLVMBBAddrMapSection));
19 changes: 3 additions & 16 deletions llvm/test/CodeGen/X86/basic-block-sections-labels.ll
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,12 @@ declare i32 @__gxx_personality_v0(...)
; CHECK-NEXT: .uleb128 .Lfunc_begin0-.Lfunc_begin0
; CHECK-NEXT: .uleb128 .LBB_END0_0-.Lfunc_begin0
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 0
; ...calls and successor info for Yk JIT...
; CHECK: .uleb128 .LBB0_1-.LBB_END0_0
; CHECK-NEXT: .uleb128 .LBB0_1-.LBB_END0_0
; CHECK-NEXT: .uleb128 .LBB_END0_1-.LBB0_1
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 1
; ...calls and successor info for Yk JIT...
; CHECK: .uleb128 .LBB0_2-.LBB_END0_1
; CHECK-NEXT: .uleb128 .LBB0_2-.LBB_END0_1
; CHECK-NEXT: .uleb128 .LBB_END0_2-.LBB0_2
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 3
; CHECK-NEXT: .byte 4
; ...calls and successor info for Yk JIT...
; CHECK: .uleb128 .LBB0_3-.LBB_END0_2
; CHECK-NEXT: .uleb128 .LBB0_3-.LBB_END0_2
; CHECK-NEXT: .uleb128 .LBB_END0_3-.LBB0_3
; CHECK-NEXT: .byte 5
; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 4

0 comments on commit c75eec9

Please sign in to comment.