Skip to content

Commit 487399a

Browse files
author
Richard Sandiford
committed
[SystemZ] Fix thinko in long branch pass
The original version of the pass could underestimate the length of a backward branch in cases like: alignment to N bytes or more ... relaxable branch A ... foo: (aligned to M<N bytes) ... bar: (aligned to N bytes) ... relaxable branch B to foo We don't add any misalignment gap for "bar" because N bytes of alignment had already been reached earlier in the function. In this case, assuming that A is relaxed can push "foo" closer to "bar", and make B appear to be in range. Similar problems can occur for forward branches. I don't think it's possible to create blocks with mixed alignments as things stand, not least because we haven't yet defined getPrefLoopAlignment() for SystemZ (that would need benchmarking). So I don't think we can test this yet. Thanks to Rafael Espíndola for spotting the bug. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182460 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 3b4b536 commit 487399a

File tree

1 file changed

+40
-26
lines changed

1 file changed

+40
-26
lines changed

lib/Target/SystemZ/SystemZLongBranch.cpp

+40-26
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,19 @@
3737
// are actually relatively cheap. It therefore doesn't seem worth spending
3838
// much compilation time on the problem. Instead, the approach we take is:
3939
//
40-
// (1) Check whether all branches can be short (the usual case). Exit the
41-
// pass if so.
42-
// (2) If one branch needs to be long, work out the address that each block
43-
// would have if all branches need to be long, as for shortening above.
44-
// (3) Relax any branch that is out of range according to this pessimistic
45-
// assumption.
40+
// (1) Work out the address that each block would have if no branches
41+
// need relaxing. Exit the pass early if all branches are in range
42+
// according to this assumption.
43+
//
44+
// (2) Work out the address that each block would have if all branches
45+
// need relaxing.
46+
//
47+
// (3) Walk through the block calculating the final address of each instruction
48+
// and relaxing those that need to be relaxed. For backward branches,
49+
// this check uses the final address of the target block, as calculated
50+
// earlier in the walk. For forward branches, this check uses the
51+
// address of the target block that was calculated in (2). Both checks
52+
// give a conservatively-correct range.
4653
//
4754
//===----------------------------------------------------------------------===//
4855

@@ -68,10 +75,7 @@ namespace {
6875

6976
// Represents positional information about a basic block.
7077
struct MBBInfo {
71-
// The address that we currently assume the block has, relative to
72-
// the start of the function. This is designed so that taking the
73-
// difference between two addresses gives a conservative upper bound
74-
// on the distance between them.
78+
// The address that we currently assume the block has.
7579
uint64_t Address;
7680

7781
// The size of the block in bytes, excluding terminators.
@@ -95,8 +99,7 @@ namespace {
9599
// instruction, otherwise it is null.
96100
MachineInstr *Branch;
97101

98-
// The current address of the terminator, in the same form as
99-
// for BlockInfo.
102+
// The address that we currently assume the terminator has.
100103
uint64_t Address;
101104

102105
// The current size of the terminator in bytes.
@@ -115,8 +118,7 @@ namespace {
115118

116119
// Used to keep track of the current position while iterating over the blocks.
117120
struct BlockPosition {
118-
// The offset from the start of the function, in the same form
119-
// as BlockInfo.
121+
// The address that we assume this position has.
120122
uint64_t Address;
121123

122124
// The number of low bits in Address that are known to be the same
@@ -146,7 +148,7 @@ namespace {
146148
bool AssumeRelaxed);
147149
TerminatorInfo describeTerminator(MachineInstr *MI);
148150
uint64_t initMBBInfo();
149-
bool mustRelaxBranch(const TerminatorInfo &Terminator);
151+
bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address);
150152
bool mustRelaxABranch();
151153
void setWorstCaseAddresses();
152154
void relaxBranch(TerminatorInfo &Terminator);
@@ -274,17 +276,19 @@ uint64_t SystemZLongBranch::initMBBInfo() {
274276
return Position.Address;
275277
}
276278

277-
// Return true if, under current assumptions, Terminator needs to be relaxed.
278-
bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator) {
279+
// Return true if, under current assumptions, Terminator would need to be
280+
// relaxed if it were placed at address Address.
281+
bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator,
282+
uint64_t Address) {
279283
if (!Terminator.Branch)
280284
return false;
281285

282286
const MBBInfo &Target = MBBs[Terminator.TargetBlock];
283-
if (Target.Address < Terminator.Address) {
284-
if (Terminator.Address - Target.Address <= MaxBackwardRange)
287+
if (Address >= Target.Address) {
288+
if (Address - Target.Address <= MaxBackwardRange)
285289
return false;
286290
} else {
287-
if (Target.Address - Terminator.Address <= MaxForwardRange)
291+
if (Target.Address - Address <= MaxForwardRange)
288292
return false;
289293
}
290294

@@ -296,7 +300,7 @@ bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator) {
296300
bool SystemZLongBranch::mustRelaxABranch() {
297301
for (SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(),
298302
TE = Terminators.end(); TI != TE; ++TI)
299-
if (mustRelaxBranch(*TI))
303+
if (mustRelaxBranch(*TI, TI->Address))
300304
return true;
301305
return false;
302306
}
@@ -337,12 +341,22 @@ void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
337341
++LongBranches;
338342
}
339343

340-
// Relax any branches that need to be relaxed, under current assumptions.
344+
// Run a shortening pass and relax any branches that need to be relaxed.
341345
void SystemZLongBranch::relaxBranches() {
342-
for (SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(),
343-
TE = Terminators.end(); TI != TE; ++TI)
344-
if (mustRelaxBranch(*TI))
345-
relaxBranch(*TI);
346+
SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
347+
BlockPosition Position(MF->getAlignment());
348+
for (SmallVector<MBBInfo, 16>::iterator BI = MBBs.begin(), BE = MBBs.end();
349+
BI != BE; ++BI) {
350+
skipNonTerminators(Position, *BI);
351+
for (unsigned BTI = 0, BTE = BI->NumTerminators; BTI != BTE; ++BTI) {
352+
assert(Position.Address <= TI->Address &&
353+
"Addresses shouldn't go forwards");
354+
if (mustRelaxBranch(*TI, Position.Address))
355+
relaxBranch(*TI);
356+
skipTerminator(Position, *TI, false);
357+
++TI;
358+
}
359+
}
346360
}
347361

348362
bool SystemZLongBranch::runOnMachineFunction(MachineFunction &F) {

0 commit comments

Comments
 (0)