[CodeGen] Use RegUnits to track register aliases (NFC)
Summary: Use RegUnits to track register aliases in PostRASink and AArch64LoadStoreOptimizer. Reviewers: thegameg, mcrosier, gberry, qcolombet, sebpop, MatzeB, t.p.northover, javed.absar Reviewed By: thegameg, sebpop Subscribers: javed.absar, llvm-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D45695 llvm-svn: 331066
This commit is contained in:
parent
8a937e00d8
commit
47aece1344
|
@ -16,6 +16,7 @@
|
|||
#define LLVM_CODEGEN_LIVEREGUNITS_H
|
||||
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
||||
#include "llvm/MC/LaneBitmask.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
|
@ -40,6 +41,36 @@ public:
|
|||
init(TRI);
|
||||
}
|
||||
|
||||
/// For a machine instruction \p MI, adds all register units used in
|
||||
/// \p UsedRegUnits and defined or clobbered in \p ModifiedRegUnits. This is
|
||||
/// useful when walking over a range of instructions to track registers
|
||||
/// used or defined seperately.
|
||||
static void accumulateUsedDefed(const MachineInstr &MI,
|
||||
LiveRegUnits &ModifiedRegUnits,
|
||||
LiveRegUnits &UsedRegUnits,
|
||||
const TargetRegisterInfo *TRI) {
|
||||
for (ConstMIBundleOperands O(MI); O.isValid(); ++O) {
|
||||
if (O->isRegMask())
|
||||
ModifiedRegUnits.addRegsInMask(O->getRegMask());
|
||||
if (!O->isReg())
|
||||
continue;
|
||||
unsigned Reg = O->getReg();
|
||||
if (!TargetRegisterInfo::isPhysicalRegister(Reg))
|
||||
continue;
|
||||
if (O->isDef()) {
|
||||
// Some architectures (e.g. AArch64 XZR/WZR) have registers that are
|
||||
// constant and may be used as destinations to indicate the generated
|
||||
// value is discarded. No need to track such case as a def.
|
||||
if (!TRI->isConstantPhysReg(Reg))
|
||||
ModifiedRegUnits.addReg(Reg);
|
||||
} else {
|
||||
assert(O->isUse() && "Reg operand not a def and not a use");
|
||||
UsedRegUnits.addReg(Reg);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// Initialize and clear the set.
|
||||
void init(const TargetRegisterInfo &TRI) {
|
||||
this->TRI = &TRI;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseMapInfo.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/CodeGen/LiveRegUnits.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineCombinerPattern.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
|
@ -979,11 +980,6 @@ public:
|
|||
/// even if it has glue.
|
||||
virtual bool canCopyGluedNodeDuringSchedule(SDNode *N) const { return false; }
|
||||
|
||||
/// Remember what registers the specified instruction uses and modifies.
|
||||
virtual void trackRegDefsUses(const MachineInstr &MI, BitVector &ModifiedRegs,
|
||||
BitVector &UsedRegs,
|
||||
const TargetRegisterInfo *TRI) const;
|
||||
|
||||
protected:
|
||||
/// Target-dependent implementation for foldMemoryOperand.
|
||||
/// Target-independent code in foldMemoryOperand will
|
||||
|
|
|
@ -959,8 +959,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
/// Track which registers have been modified and used.
|
||||
BitVector ModifiedRegs, UsedRegs;
|
||||
/// Track which register units have been modified and used.
|
||||
LiveRegUnits ModifiedRegUnits, UsedRegUnits;
|
||||
|
||||
/// Sink Copy instructions unused in the same block close to their uses in
|
||||
/// successors.
|
||||
|
@ -975,22 +975,17 @@ char &llvm::PostRAMachineSinkingID = PostRAMachineSinking::ID;
|
|||
INITIALIZE_PASS(PostRAMachineSinking, "postra-machine-sink",
|
||||
"PostRA Machine Sink", false, false)
|
||||
|
||||
static bool aliasWithRegsInLiveIn(MachineBasicBlock *SI,
|
||||
SmallSet<unsigned, 8> &AliasedRegs) {
|
||||
for (const auto LI : SI->liveins())
|
||||
if (AliasedRegs.count(LI.PhysReg))
|
||||
return true;
|
||||
return false;
|
||||
static bool aliasWithRegsInLiveIn(MachineBasicBlock &MBB, unsigned Reg,
|
||||
const TargetRegisterInfo *TRI) {
|
||||
LiveRegUnits LiveInRegUnits(*TRI);
|
||||
LiveInRegUnits.addLiveIns(MBB);
|
||||
return !LiveInRegUnits.available(Reg);
|
||||
}
|
||||
|
||||
static MachineBasicBlock *
|
||||
getSingleLiveInSuccBB(MachineBasicBlock &CurBB,
|
||||
ArrayRef<MachineBasicBlock *> SinkableBBs, unsigned Reg,
|
||||
const TargetRegisterInfo *TRI) {
|
||||
SmallSet<unsigned, 8> AliasedRegs;
|
||||
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
|
||||
AliasedRegs.insert(*AI);
|
||||
|
||||
// Try to find a single sinkable successor in which Reg is live-in.
|
||||
MachineBasicBlock *BB = nullptr;
|
||||
for (auto *SI : SinkableBBs) {
|
||||
|
@ -1010,7 +1005,7 @@ getSingleLiveInSuccBB(MachineBasicBlock &CurBB,
|
|||
for (auto *SI : CurBB.successors()) {
|
||||
if (SI == BB)
|
||||
continue;
|
||||
if (aliasWithRegsInLiveIn(SI, AliasedRegs))
|
||||
if (aliasWithRegsInLiveIn(*SI, Reg, TRI))
|
||||
return nullptr;
|
||||
}
|
||||
return BB;
|
||||
|
@ -1032,11 +1027,12 @@ static MachineBasicBlock *getSingleLiveInSuccBB(
|
|||
|
||||
static void clearKillFlags(MachineInstr *MI, MachineBasicBlock &CurBB,
|
||||
SmallVectorImpl<unsigned> &UsedOpsInCopy,
|
||||
BitVector &UsedRegs, const TargetRegisterInfo *TRI) {
|
||||
LiveRegUnits &UsedRegUnits,
|
||||
const TargetRegisterInfo *TRI) {
|
||||
for (auto U : UsedOpsInCopy) {
|
||||
MachineOperand &MO = MI->getOperand(U);
|
||||
unsigned SrcReg = MO.getReg();
|
||||
if (UsedRegs[SrcReg]) {
|
||||
if (!UsedRegUnits.available(SrcReg)) {
|
||||
MachineBasicBlock::iterator NI = std::next(MI->getIterator());
|
||||
for (MachineInstr &UI : make_range(NI, CurBB.end())) {
|
||||
if (UI.killsRegister(SrcReg, TRI)) {
|
||||
|
@ -1064,8 +1060,8 @@ static void updateLiveIn(MachineInstr *MI, MachineBasicBlock *SuccBB,
|
|||
static bool hasRegisterDependency(MachineInstr *MI,
|
||||
SmallVectorImpl<unsigned> &UsedOpsInCopy,
|
||||
SmallVectorImpl<unsigned> &DefedRegsInCopy,
|
||||
BitVector &ModifiedRegs,
|
||||
BitVector &UsedRegs) {
|
||||
LiveRegUnits &ModifiedRegUnits,
|
||||
LiveRegUnits &UsedRegUnits) {
|
||||
bool HasRegDependency = false;
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
MachineOperand &MO = MI->getOperand(i);
|
||||
|
@ -1075,7 +1071,7 @@ static bool hasRegisterDependency(MachineInstr *MI,
|
|||
if (!Reg)
|
||||
continue;
|
||||
if (MO.isDef()) {
|
||||
if (ModifiedRegs[Reg] || UsedRegs[Reg]) {
|
||||
if (!ModifiedRegUnits.available(Reg) || !UsedRegUnits.available(Reg)) {
|
||||
HasRegDependency = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1086,7 +1082,7 @@ static bool hasRegisterDependency(MachineInstr *MI,
|
|||
// it's not perfectly clear if skipping the internal read is safe in all
|
||||
// other targets.
|
||||
} else if (MO.isUse()) {
|
||||
if (ModifiedRegs[Reg]) {
|
||||
if (!ModifiedRegUnits.available(Reg)) {
|
||||
HasRegDependency = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1115,8 +1111,8 @@ bool PostRAMachineSinking::tryToSinkCopy(MachineBasicBlock &CurBB,
|
|||
|
||||
// Track which registers have been modified and used between the end of the
|
||||
// block and the current instruction.
|
||||
ModifiedRegs.reset();
|
||||
UsedRegs.reset();
|
||||
ModifiedRegUnits.clear();
|
||||
UsedRegUnits.clear();
|
||||
|
||||
for (auto I = CurBB.rbegin(), E = CurBB.rend(); I != E;) {
|
||||
MachineInstr *MI = &*I;
|
||||
|
@ -1127,7 +1123,8 @@ bool PostRAMachineSinking::tryToSinkCopy(MachineBasicBlock &CurBB,
|
|||
return false;
|
||||
|
||||
if (!MI->isCopy() || !MI->getOperand(0).isRenamable()) {
|
||||
TII->trackRegDefsUses(*MI, ModifiedRegs, UsedRegs, TRI);
|
||||
LiveRegUnits::accumulateUsedDefed(*MI, ModifiedRegUnits, UsedRegUnits,
|
||||
TRI);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1137,9 +1134,10 @@ bool PostRAMachineSinking::tryToSinkCopy(MachineBasicBlock &CurBB,
|
|||
SmallVector<unsigned, 2> DefedRegsInCopy;
|
||||
|
||||
// Don't sink the COPY if it would violate a register dependency.
|
||||
if (hasRegisterDependency(MI, UsedOpsInCopy, DefedRegsInCopy, ModifiedRegs,
|
||||
UsedRegs)) {
|
||||
TII->trackRegDefsUses(*MI, ModifiedRegs, UsedRegs, TRI);
|
||||
if (hasRegisterDependency(MI, UsedOpsInCopy, DefedRegsInCopy,
|
||||
ModifiedRegUnits, UsedRegUnits)) {
|
||||
LiveRegUnits::accumulateUsedDefed(*MI, ModifiedRegUnits, UsedRegUnits,
|
||||
TRI);
|
||||
continue;
|
||||
}
|
||||
assert((!UsedOpsInCopy.empty() && !DefedRegsInCopy.empty()) &&
|
||||
|
@ -1149,7 +1147,8 @@ bool PostRAMachineSinking::tryToSinkCopy(MachineBasicBlock &CurBB,
|
|||
// Don't sink if we cannot find a single sinkable successor in which Reg
|
||||
// is live-in.
|
||||
if (!SuccBB) {
|
||||
TII->trackRegDefsUses(*MI, ModifiedRegs, UsedRegs, TRI);
|
||||
LiveRegUnits::accumulateUsedDefed(*MI, ModifiedRegUnits, UsedRegUnits,
|
||||
TRI);
|
||||
continue;
|
||||
}
|
||||
assert((SuccBB->pred_size() == 1 && *SuccBB->pred_begin() == &CurBB) &&
|
||||
|
@ -1157,7 +1156,7 @@ bool PostRAMachineSinking::tryToSinkCopy(MachineBasicBlock &CurBB,
|
|||
|
||||
// Clear the kill flag if SrcReg is killed between MI and the end of the
|
||||
// block.
|
||||
clearKillFlags(MI, CurBB, UsedOpsInCopy, UsedRegs, TRI);
|
||||
clearKillFlags(MI, CurBB, UsedOpsInCopy, UsedRegUnits, TRI);
|
||||
MachineBasicBlock::iterator InsertPos = SuccBB->getFirstNonPHI();
|
||||
SuccBB->splice(InsertPos, &CurBB, MI);
|
||||
updateLiveIn(MI, SuccBB, UsedOpsInCopy, DefedRegsInCopy);
|
||||
|
@ -1172,9 +1171,9 @@ bool PostRAMachineSinking::runOnMachineFunction(MachineFunction &MF) {
|
|||
bool Changed = false;
|
||||
const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
|
||||
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
|
||||
ModifiedRegs.resize(TRI->getNumRegs());
|
||||
UsedRegs.resize(TRI->getNumRegs());
|
||||
|
||||
ModifiedRegUnits.init(*TRI);
|
||||
UsedRegUnits.init(*TRI);
|
||||
for (auto &BB : MF)
|
||||
Changed |= tryToSinkCopy(BB, MF, TRI, TII);
|
||||
|
||||
|
|
|
@ -882,33 +882,6 @@ void TargetInstrInfo::genAlternativeCodeSequence(
|
|||
reassociateOps(Root, *Prev, Pattern, InsInstrs, DelInstrs, InstIdxForVirtReg);
|
||||
}
|
||||
|
||||
void TargetInstrInfo::trackRegDefsUses(const MachineInstr &MI,
|
||||
BitVector &ModifiedRegs,
|
||||
BitVector &UsedRegs,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
for (const MachineOperand &MO : MI.operands()) {
|
||||
if (MO.isRegMask())
|
||||
ModifiedRegs.setBitsNotInMask(MO.getRegMask());
|
||||
if (!MO.isReg())
|
||||
continue;
|
||||
unsigned Reg = MO.getReg();
|
||||
if (!Reg)
|
||||
continue;
|
||||
if (MO.isDef()) {
|
||||
// Some architectures (e.g. AArch64 XZR/WZR) have registers that are
|
||||
// constant and may be used as destinations to indicate the generated
|
||||
// value is discarded. No need to track such case as a def.
|
||||
if (!TRI->isConstantPhysReg(Reg))
|
||||
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
|
||||
ModifiedRegs.set(*AI);
|
||||
} else {
|
||||
assert(MO.isUse() && "Reg operand not a def and not a use");
|
||||
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
|
||||
UsedRegs.set(*AI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TargetInstrInfo::isReallyTriviallyReMaterializableGeneric(
|
||||
const MachineInstr &MI, AliasAnalysis *AA) const {
|
||||
const MachineFunction &MF = *MI.getMF();
|
||||
|
|
|
@ -98,8 +98,8 @@ struct AArch64LoadStoreOpt : public MachineFunctionPass {
|
|||
const TargetRegisterInfo *TRI;
|
||||
const AArch64Subtarget *Subtarget;
|
||||
|
||||
// Track which registers have been modified and used.
|
||||
BitVector ModifiedRegs, UsedRegs;
|
||||
// Track which register units have been modified and used.
|
||||
LiveRegUnits ModifiedRegUnits, UsedRegUnits;
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
|
@ -1051,10 +1051,10 @@ bool AArch64LoadStoreOpt::findMatchingStore(
|
|||
if (MBBI == B)
|
||||
return false;
|
||||
|
||||
// Track which registers have been modified and used between the first insn
|
||||
// and the second insn.
|
||||
ModifiedRegs.reset();
|
||||
UsedRegs.reset();
|
||||
// Track which register units have been modified and used between the first
|
||||
// insn and the second insn.
|
||||
ModifiedRegUnits.clear();
|
||||
UsedRegUnits.clear();
|
||||
|
||||
unsigned Count = 0;
|
||||
do {
|
||||
|
@ -1073,7 +1073,7 @@ bool AArch64LoadStoreOpt::findMatchingStore(
|
|||
if (MI.mayStore() && isMatchingStore(LoadMI, MI) &&
|
||||
BaseReg == getLdStBaseOp(MI).getReg() &&
|
||||
isLdOffsetInRangeOfSt(LoadMI, MI, TII) &&
|
||||
!ModifiedRegs[getLdStRegOp(MI).getReg()]) {
|
||||
ModifiedRegUnits.available(getLdStRegOp(MI).getReg())) {
|
||||
StoreI = MBBI;
|
||||
return true;
|
||||
}
|
||||
|
@ -1081,12 +1081,12 @@ bool AArch64LoadStoreOpt::findMatchingStore(
|
|||
if (MI.isCall())
|
||||
return false;
|
||||
|
||||
// Update modified / uses register lists.
|
||||
TII->trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
|
||||
// Update modified / uses register units.
|
||||
LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
|
||||
|
||||
// Otherwise, if the base register is modified, we have no match, so
|
||||
// return early.
|
||||
if (ModifiedRegs[BaseReg])
|
||||
if (!ModifiedRegUnits.available(BaseReg))
|
||||
return false;
|
||||
|
||||
// If we encounter a store aliased with the load, return early.
|
||||
|
@ -1164,10 +1164,10 @@ AArch64LoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
|
|||
int OffsetStride = IsUnscaled ? getMemScale(FirstMI) : 1;
|
||||
bool IsPromotableZeroStore = isPromotableZeroStoreInst(FirstMI);
|
||||
|
||||
// Track which registers have been modified and used between the first insn
|
||||
// (inclusive) and the second insn.
|
||||
ModifiedRegs.reset();
|
||||
UsedRegs.reset();
|
||||
// Track which register units have been modified and used between the first
|
||||
// insn (inclusive) and the second insn.
|
||||
ModifiedRegUnits.clear();
|
||||
UsedRegUnits.clear();
|
||||
|
||||
// Remember any instructions that read/write memory between FirstMI and MI.
|
||||
SmallVector<MachineInstr *, 4> MemInsns;
|
||||
|
@ -1202,7 +1202,8 @@ AArch64LoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
|
|||
// If the unscaled offset isn't a multiple of the MemSize, we can't
|
||||
// pair the operations together: bail and keep looking.
|
||||
if (MIOffset % MemSize) {
|
||||
TII->trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
|
||||
LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits,
|
||||
UsedRegUnits, TRI);
|
||||
MemInsns.push_back(&MI);
|
||||
continue;
|
||||
}
|
||||
|
@ -1222,7 +1223,8 @@ AArch64LoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
|
|||
// the stored value is the same (i.e., WZR).
|
||||
if ((!IsUnscaled && alignTo(MinOffset, 2) != MinOffset) ||
|
||||
(IsPromotableZeroStore && Reg != getLdStRegOp(MI).getReg())) {
|
||||
TII->trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
|
||||
LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits,
|
||||
UsedRegUnits, TRI);
|
||||
MemInsns.push_back(&MI);
|
||||
continue;
|
||||
}
|
||||
|
@ -1232,7 +1234,8 @@ AArch64LoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
|
|||
// immediate offset of merging these instructions is out of range for
|
||||
// a pairwise instruction, bail and keep looking.
|
||||
if (!inBoundsForPair(IsUnscaled, MinOffset, OffsetStride)) {
|
||||
TII->trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
|
||||
LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits,
|
||||
UsedRegUnits, TRI);
|
||||
MemInsns.push_back(&MI);
|
||||
continue;
|
||||
}
|
||||
|
@ -1240,7 +1243,8 @@ AArch64LoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
|
|||
// can't express the offset of the unscaled input, bail and keep
|
||||
// looking.
|
||||
if (IsUnscaled && (alignTo(MinOffset, OffsetStride) != MinOffset)) {
|
||||
TII->trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
|
||||
LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits,
|
||||
UsedRegUnits, TRI);
|
||||
MemInsns.push_back(&MI);
|
||||
continue;
|
||||
}
|
||||
|
@ -1249,7 +1253,8 @@ AArch64LoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
|
|||
// and keep looking. A load-pair instruction with both destination
|
||||
// registers the same is UNPREDICTABLE and will result in an exception.
|
||||
if (MayLoad && Reg == getLdStRegOp(MI).getReg()) {
|
||||
TII->trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
|
||||
LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits,
|
||||
TRI);
|
||||
MemInsns.push_back(&MI);
|
||||
continue;
|
||||
}
|
||||
|
@ -1258,8 +1263,9 @@ AArch64LoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
|
|||
// the two instructions and none of the instructions between the second
|
||||
// and first alias with the second, we can combine the second into the
|
||||
// first.
|
||||
if (!ModifiedRegs[getLdStRegOp(MI).getReg()] &&
|
||||
!(MI.mayLoad() && UsedRegs[getLdStRegOp(MI).getReg()]) &&
|
||||
if (ModifiedRegUnits.available(getLdStRegOp(MI).getReg()) &&
|
||||
!(MI.mayLoad() &&
|
||||
!UsedRegUnits.available(getLdStRegOp(MI).getReg())) &&
|
||||
!mayAlias(MI, MemInsns, AA)) {
|
||||
Flags.setMergeForward(false);
|
||||
return MBBI;
|
||||
|
@ -1269,8 +1275,9 @@ AArch64LoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
|
|||
// between the two instructions and none of the instructions between the
|
||||
// first and the second alias with the first, we can combine the first
|
||||
// into the second.
|
||||
if (!ModifiedRegs[getLdStRegOp(FirstMI).getReg()] &&
|
||||
!(MayLoad && UsedRegs[getLdStRegOp(FirstMI).getReg()]) &&
|
||||
if (ModifiedRegUnits.available(getLdStRegOp(FirstMI).getReg()) &&
|
||||
!(MayLoad &&
|
||||
!UsedRegUnits.available(getLdStRegOp(FirstMI).getReg())) &&
|
||||
!mayAlias(FirstMI, MemInsns, AA)) {
|
||||
Flags.setMergeForward(true);
|
||||
return MBBI;
|
||||
|
@ -1285,12 +1292,12 @@ AArch64LoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
|
|||
if (MI.isCall())
|
||||
return E;
|
||||
|
||||
// Update modified / uses register lists.
|
||||
TII->trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
|
||||
// Update modified / uses register units.
|
||||
LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
|
||||
|
||||
// Otherwise, if the base register is modified, we have no match, so
|
||||
// return early.
|
||||
if (ModifiedRegs[BaseReg])
|
||||
if (!ModifiedRegUnits.available(BaseReg))
|
||||
return E;
|
||||
|
||||
// Update list of instructions that read/write memory.
|
||||
|
@ -1446,10 +1453,10 @@ MachineBasicBlock::iterator AArch64LoadStoreOpt::findMatchingUpdateInsnForward(
|
|||
return E;
|
||||
}
|
||||
|
||||
// Track which registers have been modified and used between the first insn
|
||||
// (inclusive) and the second insn.
|
||||
ModifiedRegs.reset();
|
||||
UsedRegs.reset();
|
||||
// Track which register units have been modified and used between the first
|
||||
// insn (inclusive) and the second insn.
|
||||
ModifiedRegUnits.clear();
|
||||
UsedRegUnits.clear();
|
||||
++MBBI;
|
||||
for (unsigned Count = 0; MBBI != E && Count < Limit; ++MBBI) {
|
||||
MachineInstr &MI = *MBBI;
|
||||
|
@ -1464,11 +1471,12 @@ MachineBasicBlock::iterator AArch64LoadStoreOpt::findMatchingUpdateInsnForward(
|
|||
return MBBI;
|
||||
|
||||
// Update the status of what the instruction clobbered and used.
|
||||
TII->trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
|
||||
LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
|
||||
|
||||
// Otherwise, if the base register is used or modified, we have no match, so
|
||||
// return early.
|
||||
if (ModifiedRegs[BaseReg] || UsedRegs[BaseReg])
|
||||
if (!ModifiedRegUnits.available(BaseReg) ||
|
||||
!UsedRegUnits.available(BaseReg))
|
||||
return E;
|
||||
}
|
||||
return E;
|
||||
|
@ -1497,10 +1505,10 @@ MachineBasicBlock::iterator AArch64LoadStoreOpt::findMatchingUpdateInsnBackward(
|
|||
return E;
|
||||
}
|
||||
|
||||
// Track which registers have been modified and used between the first insn
|
||||
// (inclusive) and the second insn.
|
||||
ModifiedRegs.reset();
|
||||
UsedRegs.reset();
|
||||
// Track which register units have been modified and used between the first
|
||||
// insn (inclusive) and the second insn.
|
||||
ModifiedRegUnits.clear();
|
||||
UsedRegUnits.clear();
|
||||
unsigned Count = 0;
|
||||
do {
|
||||
--MBBI;
|
||||
|
@ -1516,11 +1524,12 @@ MachineBasicBlock::iterator AArch64LoadStoreOpt::findMatchingUpdateInsnBackward(
|
|||
return MBBI;
|
||||
|
||||
// Update the status of what the instruction clobbered and used.
|
||||
TII->trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
|
||||
LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
|
||||
|
||||
// Otherwise, if the base register is used or modified, we have no match, so
|
||||
// return early.
|
||||
if (ModifiedRegs[BaseReg] || UsedRegs[BaseReg])
|
||||
if (!ModifiedRegUnits.available(BaseReg) ||
|
||||
!UsedRegUnits.available(BaseReg))
|
||||
return E;
|
||||
} while (MBBI != B && Count < Limit);
|
||||
return E;
|
||||
|
@ -1747,11 +1756,11 @@ bool AArch64LoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
|
|||
TRI = Subtarget->getRegisterInfo();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
|
||||
// Resize the modified and used register bitfield trackers. We do this once
|
||||
// per function and then clear the bitfield each time we optimize a load or
|
||||
// store.
|
||||
ModifiedRegs.resize(TRI->getNumRegs());
|
||||
UsedRegs.resize(TRI->getNumRegs());
|
||||
// Resize the modified and used register unit trackers. We do this once
|
||||
// per function and then clear the register units each time we optimize a load
|
||||
// or store.
|
||||
ModifiedRegUnits.init(*TRI);
|
||||
UsedRegUnits.init(*TRI);
|
||||
|
||||
bool Modified = false;
|
||||
bool enableNarrowZeroStOpt = !Subtarget->requiresStrictAlign();
|
||||
|
|
Loading…
Reference in New Issue