aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp65
1 files changed, 33 insertions, 32 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
index 4b24f7f..2e0df3c 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
@@ -278,12 +278,13 @@ static MachineInstr *getVRegDef(unsigned Reg, const MachineInstr *Insert,
}
// Test whether Reg, as defined at Def, has exactly one use. This is a
-// generalization of MachineRegisterInfo::hasOneUse that uses LiveIntervals
-// to handle complex cases.
-static bool hasOneUse(unsigned Reg, MachineInstr *Def, MachineRegisterInfo &MRI,
- MachineDominatorTree &MDT, LiveIntervals &LIS) {
+// generalization of MachineRegisterInfo::hasOneNonDBGUse that uses
+// LiveIntervals to handle complex cases.
+static bool hasOneNonDBGUse(unsigned Reg, MachineInstr *Def,
+ MachineRegisterInfo &MRI, MachineDominatorTree &MDT,
+ LiveIntervals &LIS) {
// Most registers are in SSA form here so we try a quick MRI query first.
- if (MRI.hasOneUse(Reg))
+ if (MRI.hasOneNonDBGUse(Reg))
return true;
bool HasOne = false;
@@ -525,11 +526,10 @@ static MachineInstr *moveForSingleUse(unsigned Reg, MachineOperand &Op,
LLVM_DEBUG(dbgs() << "Move for single use: "; Def->dump());
WebAssemblyDebugValueManager DefDIs(Def);
- MBB.splice(Insert, &MBB, Def);
- DefDIs.move(Insert);
+ DefDIs.sink(Insert);
LIS.handleMove(*Def);
- if (MRI.hasOneDef(Reg) && MRI.hasOneUse(Reg)) {
+ if (MRI.hasOneDef(Reg) && MRI.hasOneNonDBGUse(Reg)) {
// No one else is using this register for anything so we can just stackify
// it in place.
MFI.stackifyVReg(MRI, Reg);
@@ -537,8 +537,8 @@ static MachineInstr *moveForSingleUse(unsigned Reg, MachineOperand &Op,
// The register may have unrelated uses or defs; create a new register for
// just our one def and use so that we can stackify it.
Register NewReg = MRI.createVirtualRegister(MRI.getRegClass(Reg));
- Def->getOperand(0).setReg(NewReg);
Op.setReg(NewReg);
+ DefDIs.updateReg(NewReg);
// Tell LiveIntervals about the new register.
LIS.createAndComputeVirtRegInterval(NewReg);
@@ -551,8 +551,6 @@ static MachineInstr *moveForSingleUse(unsigned Reg, MachineOperand &Op,
MFI.stackifyVReg(MRI, NewReg);
- DefDIs.updateReg(NewReg);
-
LLVM_DEBUG(dbgs() << " - Replaced register: "; Def->dump());
}
@@ -560,6 +558,13 @@ static MachineInstr *moveForSingleUse(unsigned Reg, MachineOperand &Op,
return Def;
}
+static MachineInstr *getPrevNonDebugInst(MachineInstr *MI) {
+ for (auto *I = MI->getPrevNode(); I; I = I->getPrevNode())
+ if (!I->isDebugInstr())
+ return I;
+ return nullptr;
+}
+
/// A trivially cloneable instruction; clone it and nest the new copy with the
/// current instruction.
static MachineInstr *rematerializeCheapDef(
@@ -573,9 +578,10 @@ static MachineInstr *rematerializeCheapDef(
WebAssemblyDebugValueManager DefDIs(&Def);
Register NewReg = MRI.createVirtualRegister(MRI.getRegClass(Reg));
- TII->reMaterialize(MBB, Insert, NewReg, 0, Def, *TRI);
+ DefDIs.cloneSink(&*Insert, NewReg);
Op.setReg(NewReg);
- MachineInstr *Clone = &*std::prev(Insert);
+ MachineInstr *Clone = getPrevNonDebugInst(&*Insert);
+ assert(Clone);
LIS.InsertMachineInstrInMaps(*Clone);
LIS.createAndComputeVirtRegInterval(NewReg);
MFI.stackifyVReg(MRI, NewReg);
@@ -592,19 +598,13 @@ static MachineInstr *rematerializeCheapDef(
}
// If that was the last use of the original, delete the original.
- // Move or clone corresponding DBG_VALUEs to the 'Insert' location.
if (IsDead) {
LLVM_DEBUG(dbgs() << " - Deleting original\n");
SlotIndex Idx = LIS.getInstructionIndex(Def).getRegSlot();
LIS.removePhysRegDefAt(MCRegister::from(WebAssembly::ARGUMENTS), Idx);
LIS.removeInterval(Reg);
LIS.RemoveMachineInstrFromMaps(Def);
- Def.eraseFromParent();
-
- DefDIs.move(&*Insert);
- DefDIs.updateReg(NewReg);
- } else {
- DefDIs.clone(&*Insert, NewReg);
+ DefDIs.removeDef();
}
return Clone;
@@ -636,28 +636,26 @@ static MachineInstr *moveAndTeeForMultiUse(
MachineRegisterInfo &MRI, const WebAssemblyInstrInfo *TII) {
LLVM_DEBUG(dbgs() << "Move and tee for multi-use:"; Def->dump());
- WebAssemblyDebugValueManager DefDIs(Def);
+ const auto *RegClass = MRI.getRegClass(Reg);
+ Register TeeReg = MRI.createVirtualRegister(RegClass);
+ Register DefReg = MRI.createVirtualRegister(RegClass);
// Move Def into place.
- MBB.splice(Insert, &MBB, Def);
+ WebAssemblyDebugValueManager DefDIs(Def);
+ DefDIs.sink(Insert);
LIS.handleMove(*Def);
// Create the Tee and attach the registers.
- const auto *RegClass = MRI.getRegClass(Reg);
- Register TeeReg = MRI.createVirtualRegister(RegClass);
- Register DefReg = MRI.createVirtualRegister(RegClass);
MachineOperand &DefMO = Def->getOperand(0);
MachineInstr *Tee = BuildMI(MBB, Insert, Insert->getDebugLoc(),
TII->get(getTeeOpcode(RegClass)), TeeReg)
.addReg(Reg, RegState::Define)
.addReg(DefReg, getUndefRegState(DefMO.isDead()));
Op.setReg(TeeReg);
- DefMO.setReg(DefReg);
+ DefDIs.updateReg(DefReg);
SlotIndex TeeIdx = LIS.InsertMachineInstrInMaps(*Tee).getRegSlot();
SlotIndex DefIdx = LIS.getInstructionIndex(*Def).getRegSlot();
- DefDIs.move(Insert);
-
// Tell LiveIntervals we moved the original vreg def from Def to Tee.
LiveInterval &LI = LIS.getInterval(Reg);
LiveInterval::iterator I = LI.FindSegmentContaining(DefIdx);
@@ -674,8 +672,11 @@ static MachineInstr *moveAndTeeForMultiUse(
imposeStackOrdering(Def);
imposeStackOrdering(Tee);
- DefDIs.clone(Tee, DefReg);
- DefDIs.clone(Insert, TeeReg);
+ // Even though 'TeeReg, Reg = TEE ...', has two defs, we don't need to clone
+ // DBG_VALUEs for both of them, given that the latter will cancel the former
+ // anyway. Here we only clone DBG_VALUEs for TeeReg, which will be converted
+ // to a local index in ExplicitLocals pass.
+ DefDIs.cloneSink(Insert, TeeReg, /* CloneDef */ false);
LLVM_DEBUG(dbgs() << " - Replaced register: "; Def->dump());
LLVM_DEBUG(dbgs() << " - Tee instruction: "; Tee->dump());
@@ -876,7 +877,7 @@ bool WebAssemblyRegStackify::runOnMachineFunction(MachineFunction &MF) {
bool SameBlock = DefI->getParent() == &MBB;
bool CanMove = SameBlock && isSafeToMove(Def, &Use, Insert, MFI, MRI) &&
!TreeWalker.isOnStack(Reg);
- if (CanMove && hasOneUse(Reg, DefI, MRI, MDT, LIS)) {
+ if (CanMove && hasOneNonDBGUse(Reg, DefI, MRI, MDT, LIS)) {
Insert = moveForSingleUse(Reg, Use, DefI, MBB, Insert, LIS, MFI, MRI);
// If we are removing the frame base reg completely, remove the debug
@@ -913,7 +914,7 @@ bool WebAssemblyRegStackify::runOnMachineFunction(MachineFunction &MF) {
Register DefReg = SubsequentDef->getReg();
Register UseReg = SubsequentUse->getReg();
// TODO: This single-use restriction could be relaxed by using tees
- if (DefReg != UseReg || !MRI.hasOneUse(DefReg))
+ if (DefReg != UseReg || !MRI.hasOneNonDBGUse(DefReg))
break;
MFI.stackifyVReg(MRI, DefReg);
++SubsequentDef;