Skip to content

Commit

Permalink
Correct dwarf unwind information in function epilogue
Browse files Browse the repository at this point in the history
This patch aims to provide correct dwarf unwind information in function
epilogue for X86.
It consists of two parts. The first part inserts CFI instructions that set
appropriate cfa offset and cfa register in emitEpilogue() in
X86FrameLowering. This part is X86 specific.

The second part is platform independent and ensures that:

* CFI instructions do not affect code generation (they are not counted as
  instructions when tail duplicating or tail merging)
* Unwind information remains correct when a function is modified by
  different passes. This is done in a late pass by analyzing information
  about cfa offset and cfa register in BBs and inserting additional CFI
  directives where necessary.

Added CFIInstrInserter pass:

* analyzes each basic block to determine cfa offset and register are valid
  at its entry and exit
* verifies that outgoing cfa offset and register of predecessor blocks match
  incoming values of their successors
* inserts additional CFI directives at basic block beginning to correct the
  rule for calculating CFA

Having CFI instructions in function epilogue can cause incorrect CFA
calculation rule for some basic blocks. This can happen if, due to basic
block reordering, or the existence of multiple epilogue blocks, some of the
blocks have wrong cfa offset and register values set by the epilogue block
above them.
CFIInstrInserter is currently run only on X86, but can be used by any target
that implements support for adding CFI instructions in epilogue.

Patch by Violeta Vukobrat.

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

llvm-svn: 330706
  • Loading branch information
petar-jovanovic committed Apr 24, 2018
1 parent fce722e commit e2bfcd6
Show file tree
Hide file tree
Showing 111 changed files with 1,352 additions and 56 deletions.
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/Passes.h
Expand Up @@ -434,6 +434,9 @@ namespace llvm {
// This pass expands indirectbr instructions.
FunctionPass *createIndirectBrExpandPass();

/// Creates CFI Instruction Inserter pass. \see CFIInstrInserter.cpp
FunctionPass *createCFIInstrInserter();

} // End llvm namespace

#endif
8 changes: 8 additions & 0 deletions llvm/include/llvm/CodeGen/TargetFrameLowering.h
Expand Up @@ -345,6 +345,14 @@ class TargetFrameLowering {
return false;
return true;
}

/// Return initial CFA offset value i.e. the one valid at the beginning of the
/// function (before any stack operations).
virtual int getInitialCFAOffset(const MachineFunction &MF) const;

/// Return initial CFA register value i.e. the one valid at the beginning of
/// the function (before any stack operations).
virtual unsigned getInitialCFARegister(const MachineFunction &MF) const;
};

} // End llvm namespace
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/InitializePasses.h
Expand Up @@ -91,6 +91,7 @@ void initializeCFGOnlyViewerLegacyPassPass(PassRegistry&);
void initializeCFGPrinterLegacyPassPass(PassRegistry&);
void initializeCFGSimplifyPassPass(PassRegistry&);
void initializeCFGViewerLegacyPassPass(PassRegistry&);
void initializeCFIInstrInserterPass(PassRegistry&);
void initializeCFLAndersAAWrapperPassPass(PassRegistry&);
void initializeCFLSteensAAWrapperPassPass(PassRegistry&);
void initializeCallGraphDOTPrinterPass(PassRegistry&);
Expand Down
61 changes: 49 additions & 12 deletions llvm/lib/CodeGen/BranchFolding.cpp
Expand Up @@ -296,6 +296,11 @@ static unsigned HashEndOfMBB(const MachineBasicBlock &MBB) {
return HashMachineInstr(*I);
}

/// Whether MI should be counted as an instruction when calculating common tail.
static bool countsAsInstruction(const MachineInstr &MI) {
return !(MI.isDebugValue() || MI.isCFIInstruction());
}

/// ComputeCommonTailLength - Given two machine basic blocks, compute the number
/// of instructions they actually have in common together at their end. Return
/// iterators for the first shared instruction in each block.
Expand All @@ -310,26 +315,27 @@ static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1,
while (I1 != MBB1->begin() && I2 != MBB2->begin()) {
--I1; --I2;
// Skip debugging pseudos; necessary to avoid changing the code.
while (I1->isDebugValue()) {
while (!countsAsInstruction(*I1)) {
if (I1==MBB1->begin()) {
while (I2->isDebugValue()) {
if (I2==MBB2->begin())
while (!countsAsInstruction(*I2)) {
if (I2==MBB2->begin()) {
// I1==DBG at begin; I2==DBG at begin
return TailLen;
goto SkipTopCFIAndReturn;
}
--I2;
}
++I2;
// I1==DBG at begin; I2==non-DBG, or first of DBGs not at begin
return TailLen;
goto SkipTopCFIAndReturn;
}
--I1;
}
// I1==first (untested) non-DBG preceding known match
while (I2->isDebugValue()) {
while (!countsAsInstruction(*I2)) {
if (I2==MBB2->begin()) {
++I1;
// I1==non-DBG, or first of DBGs not at begin; I2==DBG at begin
return TailLen;
goto SkipTopCFIAndReturn;
}
--I2;
}
Expand Down Expand Up @@ -368,6 +374,37 @@ static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1,
}
++I1;
}

SkipTopCFIAndReturn:
// Ensure that I1 and I2 do not point to a CFI_INSTRUCTION. This can happen if
// I1 and I2 are non-identical when compared and then one or both of them ends
// up pointing to a CFI instruction after being incremented. For example:
/*
BB1:
...
INSTRUCTION_A
ADD32ri8 <- last common instruction
...
BB2:
...
INSTRUCTION_B
CFI_INSTRUCTION
ADD32ri8 <- last common instruction
...
*/
// When INSTRUCTION_A and INSTRUCTION_B are compared as not equal, after
// incrementing the iterators, I1 will point to ADD, however I2 will point to
// the CFI instruction. Later on, this leads to BB2 being 'hacked off' at the
// wrong place (in ReplaceTailWithBranchTo()) which results in losing this CFI
// instruction.
while (I1 != MBB1->end() && I1->isCFIInstruction()) {
++I1;
}

while (I2 != MBB2->end() && I2->isCFIInstruction()) {
++I2;
}

return TailLen;
}

Expand Down Expand Up @@ -454,7 +491,7 @@ static unsigned EstimateRuntime(MachineBasicBlock::iterator I,
MachineBasicBlock::iterator E) {
unsigned Time = 0;
for (; I != E; ++I) {
if (I->isDebugValue())
if (!countsAsInstruction(*I))
continue;
if (I->isCall())
Time += 10;
Expand Down Expand Up @@ -814,12 +851,12 @@ mergeOperations(MachineBasicBlock::iterator MBBIStartPos,
assert(MBBI != MBBIE && "Reached BB end within common tail length!");
(void)MBBIE;

if (MBBI->isDebugValue()) {
if (!countsAsInstruction(*MBBI)) {
++MBBI;
continue;
}

while ((MBBICommon != MBBIECommon) && MBBICommon->isDebugValue())
while ((MBBICommon != MBBIECommon) && !countsAsInstruction(*MBBICommon))
++MBBICommon;

assert(MBBICommon != MBBIECommon &&
Expand Down Expand Up @@ -859,7 +896,7 @@ void BranchFolder::mergeCommonTails(unsigned commonTailIndex) {
}

for (auto &MI : *MBB) {
if (MI.isDebugValue())
if (!countsAsInstruction(MI))
continue;
DebugLoc DL = MI.getDebugLoc();
for (unsigned int i = 0 ; i < NextCommonInsts.size() ; i++) {
Expand All @@ -869,7 +906,7 @@ void BranchFolder::mergeCommonTails(unsigned commonTailIndex) {
auto &Pos = NextCommonInsts[i];
assert(Pos != SameTails[i].getBlock()->end() &&
"Reached BB end within common tail");
while (Pos->isDebugValue()) {
while (!countsAsInstruction(*Pos)) {
++Pos;
assert(Pos != SameTails[i].getBlock()->end() &&
"Reached BB end within common tail");
Expand Down

0 comments on commit e2bfcd6

Please sign in to comment.