@@ -740,7 +740,7 @@ BinaryFunction::analyzeIndirectBranch(MCInst &Instruction,
740
740
//
741
741
// We handle PIC-style jump tables separately.
742
742
//
743
- if (Instruction.getNumOperands () == 1 ) {
743
+ if (Instruction.getNumPrimeOperands () == 1 ) {
744
744
// If the indirect jump is on register - try to detect if the
745
745
// register value is loaded from a memory location.
746
746
assert (Instruction.getOperand (0 ).isReg () && " register operand expected" );
@@ -1064,7 +1064,7 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
1064
1064
1065
1065
if (!IsZeroPadding) {
1066
1066
// Ignore this function. Skip to the next one in non-relocs mode.
1067
- errs () << " BOLT-ERROR : unable to disassemble instruction at offset 0x"
1067
+ errs () << " BOLT-WARNING : unable to disassemble instruction at offset 0x"
1068
1068
<< Twine::utohexstr (Offset) << " (address 0x"
1069
1069
<< Twine::utohexstr (AbsoluteInstrAddr) << " ) in function "
1070
1070
<< *this << ' \n ' ;
@@ -1098,7 +1098,7 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
1098
1098
int64_t Value;
1099
1099
const auto Result =
1100
1100
BC.MIA ->replaceImmWithSymbol (Instruction, Relocation.Symbol ,
1101
- Relocation.Addend , BC. Ctx .get (), Value);
1101
+ Relocation.Addend , Ctx.get (), Value);
1102
1102
(void )Result;
1103
1103
assert (Result && " cannot replace immediate with relocation" );
1104
1104
@@ -1125,7 +1125,7 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
1125
1125
// or a recursive call.
1126
1126
bool IsCall = MIA->isCall (Instruction);
1127
1127
const bool IsCondBranch = MIA->isConditionalBranch (Instruction);
1128
- MCSymbol *TargetSymbol{ nullptr } ;
1128
+ MCSymbol *TargetSymbol = nullptr ;
1129
1129
1130
1130
if (IsCall && containsAddress (TargetAddress)) {
1131
1131
if (TargetAddress == getAddress ()) {
@@ -1154,7 +1154,7 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
1154
1154
<< " : replacing with nop.\n " );
1155
1155
BC.MIA ->createNoop (Instruction);
1156
1156
if (IsCondBranch) {
1157
- // Register branch function profile validation.
1157
+ // Register branch offset for profile validation.
1158
1158
IgnoredBranches.emplace_back (Offset, Offset + Size);
1159
1159
}
1160
1160
goto add_instruction;
@@ -1182,10 +1182,6 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
1182
1182
<< Twine::utohexstr (AbsoluteInstrAddr) << " .\n " ;
1183
1183
}
1184
1184
}
1185
- // TODO: A better way to do this would be using annotations for
1186
- // MCInst objects.
1187
- TailCallOffsets.emplace (std::make_pair (Offset,
1188
- TargetAddress));
1189
1185
IsCall = true ;
1190
1186
}
1191
1187
@@ -1231,34 +1227,28 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
1231
1227
// Add taken branch info.
1232
1228
TakenBranches.emplace_back (Offset, TargetAddress - getAddress ());
1233
1229
}
1234
- if (IsCondBranch) {
1235
- // Add fallthrough branch info.
1236
- FTBranches.emplace_back (Offset, Offset + Size);
1237
- }
1238
-
1239
- const bool isIndirect =
1240
- ((IsCall || !IsCondBranch) && MIA->isIndirectBranch (Instruction));
1241
-
1242
1230
Instruction.clear ();
1243
1231
Instruction.addOperand (
1244
1232
MCOperand::createExpr (
1245
1233
MCSymbolRefExpr::create (TargetSymbol,
1246
1234
MCSymbolRefExpr::VK_None,
1247
1235
*Ctx)));
1248
1236
1249
- if (BranchData) {
1237
+ // Record call offset for profile matching.
1238
+ if (IsCall) {
1239
+ MIA->addAnnotation (Ctx.get (), Instruction, " Offset" , Offset);
1240
+ }
1241
+ if (IsCondBranch) {
1242
+ // Add fallthrough branch info.
1243
+ FTBranches.emplace_back (Offset, Offset + Size);
1250
1244
if (IsCall) {
1251
- MIA->addAnnotation (Ctx.get (), Instruction, " EdgeCountData" , Offset);
1252
- }
1253
- if (isIndirect) {
1254
- MIA->addAnnotation (Ctx.get (), Instruction, " IndirectBranchData" ,
1255
- Offset);
1245
+ MIA->setConditionalTailCall (Instruction, TargetAddress);
1256
1246
}
1257
1247
}
1258
1248
} else {
1259
1249
// Could not evaluate branch. Should be an indirect call or an
1260
1250
// indirect branch. Bail out on the latter case.
1261
- bool MaybeEdgeCountData = false ;
1251
+ MIA-> addAnnotation (Ctx. get (), Instruction, " Offset " , Offset) ;
1262
1252
if (MIA->isIndirectBranch (Instruction)) {
1263
1253
auto Result = analyzeIndirectBranch (Instruction, Size, Offset);
1264
1254
switch (Result) {
@@ -1269,47 +1259,27 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
1269
1259
auto Result = MIA->convertJmpToTailCall (Instruction);
1270
1260
(void )Result;
1271
1261
assert (Result);
1272
- if (BranchData) {
1273
- MIA->addAnnotation (Ctx.get (), Instruction, " IndirectBranchData" ,
1274
- Offset);
1275
- }
1276
1262
}
1277
1263
break ;
1278
1264
case IndirectBranchType::POSSIBLE_JUMP_TABLE:
1279
1265
case IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE:
1280
1266
if (opts::JumpTables == JTS_NONE)
1281
1267
IsSimple = false ;
1282
- MaybeEdgeCountData = true ;
1283
1268
break ;
1284
1269
case IndirectBranchType::UNKNOWN:
1285
1270
// Keep processing. We'll do more checks and fixes in
1286
1271
// postProcessIndirectBranches().
1287
- MaybeEdgeCountData = true ;
1288
- if (BranchData) {
1289
- MIA->addAnnotation (Ctx.get (),
1290
- Instruction,
1291
- " MaybeIndirectBranchData" ,
1292
- Offset);
1293
- }
1294
1272
break ;
1295
1273
};
1296
- } else if (MIA->isCall (Instruction)) {
1297
- if (BranchData) {
1298
- MIA->addAnnotation (Ctx.get (), Instruction, " IndirectBranchData" ,
1299
- Offset);
1300
- }
1301
- }
1302
- if (BranchData) {
1303
- const char * AttrName =
1304
- MaybeEdgeCountData ? " MaybeEdgeCountData" : " EdgeCountData" ;
1305
- MIA->addAnnotation (Ctx.get (), Instruction, AttrName, Offset);
1306
1274
}
1307
1275
// Indirect call. We only need to fix it if the operand is RIP-relative
1308
1276
if (IsSimple && MIA->hasRIPOperand (Instruction)) {
1309
1277
if (!handleRIPOperand (Instruction, AbsoluteInstrAddr, Size)) {
1310
1278
errs () << " BOLT-ERROR: cannot handle RIP operand at 0x"
1311
1279
<< Twine::utohexstr (AbsoluteInstrAddr)
1312
1280
<< " . Skipping function " << *this << " .\n " ;
1281
+ if (opts::Relocs)
1282
+ exit (1 );
1313
1283
IsSimple = false ;
1314
1284
}
1315
1285
}
@@ -1320,6 +1290,8 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
1320
1290
errs () << " BOLT-ERROR: cannot handle RIP operand at 0x"
1321
1291
<< Twine::utohexstr (AbsoluteInstrAddr)
1322
1292
<< " . Skipping function " << *this << " .\n " ;
1293
+ if (opts::Relocs)
1294
+ exit (1 );
1323
1295
IsSimple = false ;
1324
1296
}
1325
1297
}
@@ -1336,7 +1308,6 @@ void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
1336
1308
1337
1309
postProcessJumpTables ();
1338
1310
1339
- // Update state.
1340
1311
updateState (State::Disassembled);
1341
1312
}
1342
1313
@@ -1402,12 +1373,6 @@ bool BinaryFunction::postProcessIndirectBranches() {
1402
1373
// it must be a tail call.
1403
1374
if (layout_size () == 1 ) {
1404
1375
BC.MIA ->convertJmpToTailCall (Instr);
1405
- BC.MIA ->renameAnnotation (Instr,
1406
- " MaybeEdgeCountData" ,
1407
- " EdgeCountData" );
1408
- BC.MIA ->renameAnnotation (Instr,
1409
- " MaybeIndirectBranchData" ,
1410
- " IndirectBranchData" );
1411
1376
return true ;
1412
1377
}
1413
1378
@@ -1487,12 +1452,6 @@ bool BinaryFunction::postProcessIndirectBranches() {
1487
1452
return false ;
1488
1453
}
1489
1454
BC.MIA ->convertJmpToTailCall (Instr);
1490
- BC.MIA ->renameAnnotation (Instr,
1491
- " MaybeEdgeCountData" ,
1492
- " EdgeCountData" );
1493
- BC.MIA ->renameAnnotation (Instr,
1494
- " MaybeIndirectBranchData" ,
1495
- " IndirectBranchData" );
1496
1455
}
1497
1456
}
1498
1457
return true ;
@@ -1573,15 +1532,14 @@ bool BinaryFunction::buildCFG() {
1573
1532
// unconditional branch, and the unconditional branch is not
1574
1533
// a destination of another branch. In the latter case, the
1575
1534
// basic block will consist of a single unconditional branch
1576
- // (missed optimization opportunity? ).
1535
+ // (missed "double-jump" optimization ).
1577
1536
//
1578
1537
// Created basic blocks are sorted in layout order since they are
1579
1538
// created in the same order as instructions, and instructions are
1580
1539
// sorted by offsets.
1581
1540
BinaryBasicBlock *InsertBB{nullptr };
1582
1541
BinaryBasicBlock *PrevBB{nullptr };
1583
1542
bool IsLastInstrNop{false };
1584
- bool IsPreviousInstrTailCall{false };
1585
1543
const MCInst *PrevInstr{nullptr };
1586
1544
1587
1545
auto addCFIPlaceholders =
@@ -1615,11 +1573,13 @@ bool BinaryFunction::buildCFG() {
1615
1573
}
1616
1574
if (!InsertBB) {
1617
1575
// It must be a fallthrough or unreachable code. Create a new block unless
1618
- // we see an unconditional branch following a conditional one.
1576
+ // we see an unconditional branch following a conditional one. The latter
1577
+ // should not be a conditional tail call.
1619
1578
assert (PrevBB && " no previous basic block for a fall through" );
1620
1579
assert (PrevInstr && " no previous instruction for a fall through" );
1621
1580
if (MIA->isUnconditionalBranch (Instr) &&
1622
- !MIA->isUnconditionalBranch (*PrevInstr) && !IsPreviousInstrTailCall) {
1581
+ !MIA->isUnconditionalBranch (*PrevInstr) &&
1582
+ !MIA->getConditionalTailCall (*PrevInstr)) {
1623
1583
// Temporarily restore inserter basic block.
1624
1584
InsertBB = PrevBB;
1625
1585
} else {
@@ -1637,16 +1597,10 @@ bool BinaryFunction::buildCFG() {
1637
1597
uint32_t InsertIndex = InsertBB->addInstruction (Instr);
1638
1598
PrevInstr = &Instr;
1639
1599
1640
- // Record whether this basic block is terminated with a tail call.
1641
- auto TCI = TailCallOffsets.find (Offset);
1642
- if (TCI != TailCallOffsets.end ()) {
1643
- uint64_t TargetAddr = TCI->second ;
1600
+ // Record conditional tail call info.
1601
+ if (const auto CTCDest = MIA->getConditionalTailCall (Instr)) {
1644
1602
TailCallTerminatedBlocks.emplace (
1645
- std::make_pair (InsertBB,
1646
- TailCallInfo (Offset, InsertIndex, TargetAddr)));
1647
- IsPreviousInstrTailCall = true ;
1648
- } else {
1649
- IsPreviousInstrTailCall = false ;
1603
+ std::make_pair (InsertBB, TailCallInfo (Offset, InsertIndex, *CTCDest)));
1650
1604
}
1651
1605
1652
1606
// Add associated CFI instrs. We always add the CFI instruction that is
@@ -1821,9 +1775,7 @@ bool BinaryFunction::buildCFG() {
1821
1775
1822
1776
// Check if the last instruction is a conditional jump that serves as a tail
1823
1777
// call.
1824
- bool IsCondTailCall = MIA->isConditionalBranch (*LastInstIter) &&
1825
- TailCallTerminatedBlocks.count (BB);
1826
-
1778
+ const auto IsCondTailCall = MIA->getConditionalTailCall (*LastInstIter);
1827
1779
if (BB->succ_size () == 0 ) {
1828
1780
if (IsCondTailCall) {
1829
1781
// Conditional tail call without profile data for non-taken branch.
@@ -1915,7 +1867,6 @@ bool BinaryFunction::buildCFG() {
1915
1867
// NB: don't clear Labels list as we may need them if we mark the function
1916
1868
// as non-simple later in the process of discovering extra entry points.
1917
1869
clearList (Instructions);
1918
- clearList (TailCallOffsets);
1919
1870
clearList (TailCallTerminatedBlocks);
1920
1871
clearList (OffsetToCFI);
1921
1872
clearList (TakenBranches);
@@ -4384,7 +4335,7 @@ DynoStats BinaryFunction::getDynoStats() const {
4384
4335
if (!BC.MIA ->isCall (Instr))
4385
4336
continue ;
4386
4337
uint64_t CallFreq = BBExecutionCount;
4387
- if (BC.MIA ->isCTC (Instr)) {
4338
+ if (BC.MIA ->getConditionalTailCall (Instr)) {
4388
4339
CallFreq = 0 ;
4389
4340
if (auto FreqOrErr =
4390
4341
BC.MIA ->tryGetAnnotationAs <uint64_t >(Instr, " CTCTakenFreq" )) {
@@ -4444,7 +4395,7 @@ DynoStats BinaryFunction::getDynoStats() const {
4444
4395
}
4445
4396
4446
4397
// CTCs
4447
- if (BC.MIA ->isCTC (*CondBranch)) {
4398
+ if (BC.MIA ->getConditionalTailCall (*CondBranch)) {
4448
4399
if (BB->branch_info_begin () != BB->branch_info_end ())
4449
4400
Stats[DynoStats::UNCOND_BRANCHES] += BB->branch_info_begin ()->Count ;
4450
4401
continue ;
0 commit comments