Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
lib/CodeGen/MachineBasicBlock.cpp
Show All 29 Lines | |||||
#include "llvm/Support/DataTypes.h" | #include "llvm/Support/DataTypes.h" | ||||
#include "llvm/Support/Debug.h" | #include "llvm/Support/Debug.h" | ||||
#include "llvm/Support/raw_ostream.h" | #include "llvm/Support/raw_ostream.h" | ||||
#include "llvm/Target/TargetInstrInfo.h" | #include "llvm/Target/TargetInstrInfo.h" | ||||
#include "llvm/Target/TargetMachine.h" | #include "llvm/Target/TargetMachine.h" | ||||
#include "llvm/Target/TargetRegisterInfo.h" | #include "llvm/Target/TargetRegisterInfo.h" | ||||
#include "llvm/Target/TargetSubtargetInfo.h" | #include "llvm/Target/TargetSubtargetInfo.h" | ||||
#include <algorithm> | #include <algorithm> | ||||
#include <queue> | |||||
#include <set> | |||||
using namespace llvm; | using namespace llvm; | ||||
#define DEBUG_TYPE "codegen" | #define DEBUG_TYPE "codegen" | ||||
MachineBasicBlock::MachineBasicBlock(MachineFunction &MF, const BasicBlock *B) | MachineBasicBlock::MachineBasicBlock(MachineFunction &MF, const BasicBlock *B) | ||||
: BB(B), Number(-1), xParent(&MF) { | : BB(B), Number(-1), xParent(&MF) { | ||||
Insts.Parent = this; | Insts.Parent = this; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 792 Lines • ▼ Show 20 Lines | for (SmallVectorImpl<MachineInstr*>::iterator I = Terminators.begin(), | ||||
E = Terminators.end(); I != E; ++I) { | E = Terminators.end(); I != E; ++I) { | ||||
if (!is_contained(NewTerminators, *I)) | if (!is_contained(NewTerminators, *I)) | ||||
Indexes->removeMachineInstrFromMaps(**I); | Indexes->removeMachineInstrFromMaps(**I); | ||||
} | } | ||||
} | } | ||||
// Insert unconditional "jump Succ" instruction in NMBB if necessary. | // Insert unconditional "jump Succ" instruction in NMBB if necessary. | ||||
NMBB->addSuccessor(Succ); | NMBB->addSuccessor(Succ); | ||||
// Recalculate CFI info for this block and update its successors. | |||||
recalculateCFIInfo(true); | |||||
updateCFIInfoSucc(); | |||||
// Recalculate CFI info for NMBB and update its successors. | |||||
NMBB->recalculateCFIInfo(false, getOutgoingCFAOffset(), | |||||
getOutgoingCFARegister(), | |||||
getAdjustOutgoingCFAOffset()); | |||||
NMBB->updateCFIInfoSucc(); | |||||
if (!NMBB->isLayoutSuccessor(Succ)) { | if (!NMBB->isLayoutSuccessor(Succ)) { | ||||
SmallVector<MachineOperand, 4> Cond; | SmallVector<MachineOperand, 4> Cond; | ||||
const TargetInstrInfo *TII = getParent()->getSubtarget().getInstrInfo(); | const TargetInstrInfo *TII = getParent()->getSubtarget().getInstrInfo(); | ||||
TII->insertBranch(*NMBB, Succ, nullptr, Cond, DL); | TII->insertBranch(*NMBB, Succ, nullptr, Cond, DL); | ||||
if (Indexes) { | if (Indexes) { | ||||
for (MachineInstr &MI : NMBB->instrs()) { | for (MachineInstr &MI : NMBB->instrs()) { | ||||
// Some instructions may have been moved to NMBB by updateTerminator(), | // Some instructions may have been moved to NMBB by updateTerminator(), | ||||
▲ Show 20 Lines • Show All 484 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
MachineBasicBlock::livein_iterator MachineBasicBlock::livein_begin() const { | MachineBasicBlock::livein_iterator MachineBasicBlock::livein_begin() const { | ||||
assert(getParent()->getProperties().hasProperty( | assert(getParent()->getProperties().hasProperty( | ||||
MachineFunctionProperties::Property::TracksLiveness) && | MachineFunctionProperties::Property::TracksLiveness) && | ||||
"Liveness information is accurate"); | "Liveness information is accurate"); | ||||
return LiveIns.begin(); | return LiveIns.begin(); | ||||
} | } | ||||
void MachineBasicBlock::updateCFIInfo(MachineBasicBlock::iterator Pos) { | |||||
// Used for calculating outgoing cfa offset when CFI instruction added at Pos | |||||
// is def_cfa or def_cfa_offset. | |||||
/* For example: | |||||
... | |||||
.cfi_adjust_cfa_offset 4 | |||||
... | |||||
.cfi_adjust_cfa_offset 4 | |||||
... | |||||
.cfi_def_cfa_offset 16 <---- newly added CFI instruction at Pos | |||||
... | |||||
.cfi_adjust_cfa_offset 4 | |||||
... | |||||
Once def_cfa_offset is inserted, outgoing cfa offset is no longer | |||||
calculated as incoming offset incremented by the sum of all adjustments | |||||
(12). It becomes equal to the offset set by the added CFI instruction (16) | |||||
incremented by the sum of adjustments below it (4). Adjustments above the | |||||
added def_cfa_offset directive don't have effect below it anymore and | |||||
therefore don't affect the value of outgoing cfa offset. | |||||
*/ | |||||
int AdjustAmount = 0; | |||||
// Amount of adjustment that should be substracted from successors when | |||||
// updating them so that the adjustment that they inherit from this block | |||||
// becomes equal to AdjustAmount. AdjustSubtract is equal to the difference | |||||
// between the sum of adjustments before and after inserting a CFI | |||||
// instruction that sets an absolute offset. | |||||
int AdjustSubtract = 0; | |||||
// Used to check if outgoing cfa offset should be updated or not (when def_cfa | |||||
// is inserted). | |||||
bool ShouldSetOffset = true; | |||||
// Used to check if outgoing cfa register should be updated or not (when | |||||
// def_cfa is inserted). | |||||
bool ShouldSetRegister = true; | |||||
const std::vector<MCCFIInstruction> CFIInstructions = | |||||
getParent()->getFrameInstructions(); | |||||
MCCFIInstruction CFI = CFIInstructions[Pos->getOperand(0).getCFIIndex()]; | |||||
// Type of the CFI instruction that was inserted. | |||||
MCCFIInstruction::OpType CFIType = CFI.getOperation(); | |||||
// Check if there are already existing CFI instructions below Pos and see if | |||||
// outgoing CFI info should be updated or not. | |||||
for (MachineBasicBlock::reverse_iterator RI = rbegin(); | |||||
RI != Pos.getReverse(); ++RI) { | |||||
if (RI->isCFIInstruction()) { | |||||
MCCFIInstruction::OpType RIType = | |||||
CFIInstructions[RI->getOperand(0).getCFIIndex()].getOperation(); | |||||
switch (RIType) { | |||||
case MCCFIInstruction::OpAdjustCfaOffset: | |||||
AdjustAmount += | |||||
CFIInstructions[RI->getOperand(0).getCFIIndex()].getOffset(); | |||||
break; | |||||
case MCCFIInstruction::OpDefCfaOffset: | |||||
// CFI instruction doesn't affect outgoing cfa offset if there is | |||||
// already a def_cfa_offset instruction below it. | |||||
if (CFIType == MCCFIInstruction::OpDefCfaOffset || | |||||
CFIType == MCCFIInstruction::OpAdjustCfaOffset) | |||||
return; | |||||
if (CFIType == MCCFIInstruction::OpDefCfa) { | |||||
// CFI instruction doesn't affect outgoing cfa offset and register | |||||
// if there are both def_cfa_offset and def_cfa_register | |||||
// instructions below it. | |||||
if (!ShouldSetRegister) return; | |||||
ShouldSetOffset = false; | |||||
} | |||||
break; | |||||
case MCCFIInstruction::OpDefCfaRegister: | |||||
// CFI instruction doesn't affect outgoing cfa register if there is | |||||
// already a def_cfa_register instruction below it. | |||||
if (CFIType == MCCFIInstruction::OpDefCfaRegister) return; | |||||
if (CFIType == MCCFIInstruction::OpDefCfa) { | |||||
// CFI instruction doesn't affect outgoing cfa offset and register | |||||
// if there are both def_cfa_offset and def_cfa_register | |||||
// instructions below it. | |||||
if (!ShouldSetOffset) return; | |||||
ShouldSetRegister = false; | |||||
} | |||||
break; | |||||
case MCCFIInstruction::OpDefCfa: | |||||
// CFI instruction doesn't affect outgoing cfa offset and register if | |||||
// there is already a def_cfa instruction below it. | |||||
if (CFIType == MCCFIInstruction::OpDefCfaRegister || | |||||
CFIType == MCCFIInstruction::OpDefCfaOffset || | |||||
CFIType == MCCFIInstruction::OpDefCfa || | |||||
CFIType == MCCFIInstruction::OpAdjustCfaOffset) | |||||
return; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
// Update the outgoing CFI info based on the added CFI instruction. | |||||
switch (CFIType) { | |||||
case MCCFIInstruction::OpAdjustCfaOffset: | |||||
setAdjustOutgoingCFAOffset(getAdjustOutgoingCFAOffset() + | |||||
CFI.getOffset()); | |||||
updateAdjustOffsetSucc(CFI.getOffset()); | |||||
break; | |||||
case MCCFIInstruction::OpDefCfaOffset: | |||||
setOutgoingCFAOffset(CFI.getOffset()); | |||||
AdjustSubtract = getAdjustOutgoingCFAOffset() - AdjustAmount; | |||||
setAdjustOutgoingCFAOffset(AdjustAmount); | |||||
updateAdjustOffsetSucc(-AdjustSubtract); | |||||
break; | |||||
case MCCFIInstruction::OpDefCfaRegister: | |||||
setOutgoingCFARegister(CFI.getRegister()); | |||||
break; | |||||
case MCCFIInstruction::OpDefCfa: | |||||
if (ShouldSetOffset) { | |||||
setOutgoingCFAOffset(CFI.getOffset()); | |||||
AdjustSubtract = getAdjustOutgoingCFAOffset() - AdjustAmount; | |||||
setAdjustOutgoingCFAOffset(AdjustAmount); | |||||
updateAdjustOffsetSucc(-AdjustSubtract); | |||||
} | |||||
if (ShouldSetRegister) setOutgoingCFARegister(CFI.getRegister()); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
void MachineBasicBlock::updateCFIInfoSucc() { | |||||
// Blocks whose successors' CFI info should be updated. | |||||
std::queue<MachineBasicBlock *> Successors; | |||||
// Keep track of basic blocks that have already been put in the Successors | |||||
// queue. | |||||
std::set<MachineBasicBlock *> ProcessedMBBs; | |||||
thegameg: `SmallPtrSet<MachineBasicBlock *>` ? | |||||
// Start with updating CFI info for direct successors of this block. | |||||
Successors.push(this); | |||||
ProcessedMBBs.insert(this); | |||||
// Go through the successors and update their CFI info if needed. | |||||
while (!Successors.empty()) { | |||||
MachineBasicBlock *CurrSucc = Successors.front(); | |||||
Successors.pop(); | |||||
// Update CFI info for CurrSucc's successors. | |||||
for (auto Succ : CurrSucc->successors()) { | |||||
if (ProcessedMBBs.find(Succ) != ProcessedMBBs.end()) continue; | |||||
if (Succ->getIncomingCFAOffset() == CurrSucc->getOutgoingCFAOffset() && | |||||
Succ->getIncomingCFARegister() == CurrSucc->getOutgoingCFARegister()) | |||||
continue; | |||||
bool ChangedOutgoingInfo = false; | |||||
// Do not update cfa offset if the existing value matches the new. | |||||
if (Succ->getIncomingCFAOffset() != CurrSucc->getOutgoingCFAOffset()) { | |||||
// If the block doesn't have a def_cfa_offset or def_cfa directive, | |||||
// update its outgoing offset. | |||||
if (!Succ->hasDefOffset()) { | |||||
Succ->setOutgoingCFAOffset(CurrSucc->getOutgoingCFAOffset()); | |||||
ChangedOutgoingInfo = true; | |||||
} | |||||
Succ->setIncomingCFAOffset(CurrSucc->getOutgoingCFAOffset()); | |||||
} | |||||
// Do not update cfa register if the existing value matches the new. | |||||
if (Succ->getIncomingCFARegister() != | |||||
CurrSucc->getOutgoingCFARegister()) { | |||||
Succ->setIncomingCFARegister(CurrSucc->getOutgoingCFARegister()); | |||||
// If the block doesn't have a def_cfa_register or def_cfa directive, | |||||
// update its outgoing register. | |||||
if (!Succ->hasDefRegister()) { | |||||
Succ->setOutgoingCFARegister(Succ->getIncomingCFARegister()); | |||||
ChangedOutgoingInfo = true; | |||||
} | |||||
} | |||||
ProcessedMBBs.insert(Succ); | |||||
// If Succ's outgoing CFI info has been changed, it's successors should be | |||||
// updated as well. | |||||
if (ChangedOutgoingInfo) Successors.push(Succ); | |||||
} | |||||
} | |||||
} | |||||
void MachineBasicBlock::updateAdjustOffsetSucc(int AdjustOffset) { | |||||
if (!AdjustOffset) return; | |||||
// Blocks whose successors' cfa offset adjustments should be updated. | |||||
std::queue<MachineBasicBlock *> Successors; | |||||
// Keep track of basic blocks that have already been put in the Successors | |||||
// queue. | |||||
std::set<MachineBasicBlock *> ProcessedMBBs; | |||||
thegamegUnsubmitted Not Done ReplyInline ActionsSmallPtrSet<MachineBasicBlock *> ? thegameg: `SmallPtrSet<MachineBasicBlock *>` ? | |||||
// Start with updating CFI info for direct successors of this block. | |||||
Successors.push(this); | |||||
ProcessedMBBs.insert(this); | |||||
// Go through the successors and update their CFI info if needed. | |||||
while (!Successors.empty()) { | |||||
MachineBasicBlock *CurrSucc = Successors.front(); | |||||
Successors.pop(); | |||||
// Update CFI info for CurrSucc's successors. | |||||
for (auto Succ : CurrSucc->successors()) { | |||||
if (ProcessedMBBs.find(Succ) != ProcessedMBBs.end()) continue; | |||||
bool ChangedOutgoingInfo = false; | |||||
// If the block doesn't have a def_cfa_offset or def_cfa directive, | |||||
// update its outgoing offset adjustment. | |||||
if (!Succ->hasDefOffset()) { | |||||
Succ->setAdjustOutgoingCFAOffset(Succ->getAdjustOutgoingCFAOffset() + | |||||
AdjustOffset); | |||||
ChangedOutgoingInfo = true; | |||||
} | |||||
Succ->setAdjustIncomingCFAOffset(Succ->getAdjustIncomingCFAOffset() + | |||||
AdjustOffset); | |||||
ProcessedMBBs.insert(Succ); | |||||
// If Succ's outgoing CFI info has been changed, it's successors should be | |||||
// updated as well. | |||||
if (ChangedOutgoingInfo) Successors.push(Succ); | |||||
} | |||||
} | |||||
} | |||||
void MachineBasicBlock::recalculateCFIInfo(bool UseExistingIncoming, | |||||
int NewIncomingOffset, | |||||
unsigned NewIncomingRegister, | |||||
int AdjustIncomingOffset) { | |||||
// Outgoing cfa offset set by the block. | |||||
int SetOffset; | |||||
// Outgoing cfa register set by the block. | |||||
unsigned SetRegister; | |||||
int AdjustOffset = 0; | |||||
const std::vector<MCCFIInstruction> &Instrs = | |||||
getParent()->getFrameInstructions(); | |||||
// Set initial values to SetOffset and SetRegister. Use existing incoming | |||||
// values or values passed as arguments. | |||||
if (!UseExistingIncoming) { | |||||
// Set new incoming cfa offset and register values. | |||||
setIncomingCFAOffset(NewIncomingOffset); | |||||
setIncomingCFARegister(NewIncomingRegister); | |||||
setAdjustIncomingCFAOffset(AdjustIncomingOffset); | |||||
} | |||||
SetOffset = getIncomingCFAOffset(); | |||||
SetRegister = getIncomingCFARegister(); | |||||
setDefOffset(false); | |||||
setDefRegister(false); | |||||
// Determine cfa offset and register set by the block. | |||||
for (MachineBasicBlock::iterator MI = begin(); MI != end(); ++MI) { | |||||
if (MI->isCFIInstruction()) { | |||||
unsigned CFIIndex = MI->getOperand(0).getCFIIndex(); | |||||
const MCCFIInstruction &CFI = Instrs[CFIIndex]; | |||||
if (CFI.getOperation() == MCCFIInstruction::OpDefCfaRegister) { | |||||
SetRegister = CFI.getRegister(); | |||||
setDefRegister(true); | |||||
} else if (CFI.getOperation() == MCCFIInstruction::OpDefCfaOffset) { | |||||
SetOffset = CFI.getOffset(); | |||||
setDefOffset(true); | |||||
AdjustOffset = 0; | |||||
} else if (CFI.getOperation() == MCCFIInstruction::OpAdjustCfaOffset) { | |||||
AdjustOffset += CFI.getOffset(); | |||||
} else if (CFI.getOperation() == MCCFIInstruction::OpDefCfa) { | |||||
SetRegister = CFI.getRegister(); | |||||
SetOffset = CFI.getOffset(); | |||||
setDefOffset(true); | |||||
setDefRegister(true); | |||||
AdjustOffset = 0; | |||||
} | |||||
} | |||||
} | |||||
// Update outgoing CFI info. | |||||
setOutgoingCFAOffset(SetOffset); | |||||
setOutgoingCFARegister(SetRegister); | |||||
if (!hasDefOffset()) | |||||
AdjustOffset += getAdjustIncomingCFAOffset(); | |||||
setAdjustOutgoingCFAOffset(AdjustOffset); | |||||
} | |||||
void MachineBasicBlock::mergeCFIInfo(MachineBasicBlock *MBB) { | |||||
// Update CFI info. This basic block acquires MBB's outgoing cfa offset and | |||||
// register values. | |||||
setOutgoingCFAOffset(MBB->getOutgoingCFAOffset()); | |||||
setOutgoingCFARegister(MBB->getOutgoingCFARegister()); | |||||
setDefOffset(hasDefOffset() || MBB->hasDefOffset()); | |||||
setDefRegister(hasDefRegister() || MBB->hasDefRegister()); | |||||
setAdjustOutgoingCFAOffset(MBB->getAdjustOutgoingCFAOffset()); | |||||
} |
SmallPtrSet<MachineBasicBlock *> ?