Index: lib/Target/WebAssembly/WebAssemblyRegStackify.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyRegStackify.cpp +++ lib/Target/WebAssembly/WebAssemblyRegStackify.cpp @@ -474,26 +474,81 @@ } } -static void MoveDebugValues(unsigned Reg, MachineInstr *Insert, - MachineBasicBlock &MBB, MachineRegisterInfo &MRI) { - for (auto &Op : MRI.reg_operands(Reg)) { - MachineInstr *MI = Op.getParent(); - assert(MI != nullptr); - if (MI->isDebugValue() && MI->getParent() == &MBB) - MBB.splice(Insert, &MBB, MI); +class AttachedDebugValues { + unsigned OpReg; + MachineBasicBlock *OpMBB; + SmallVector Operands; + SmallPtrSet Instrs; + +public: + AttachedDebugValues(unsigned Reg, MachineInstr *Def, MachineBasicBlock &MBB, + MachineRegisterInfo &MRI) + : OpReg(Reg), OpMBB(&MBB) { + // Build set of instructions with the same Reg definitions. + SmallPtrSet Defs; + for (auto &Op : MRI.reg_operands(Reg)) { + if (Op.isDef() && Defs.find(Op.getParent()) == Defs.end()) + Defs.insert(Op.getParent()); + } + + for (auto &Op : MRI.reg_operands(Reg)) { + MachineInstr *MI = Op.getParent(); + assert(MI != nullptr); + if (!MI->isDebugValue() || MI->getParent() != &MBB) + continue; + // Scan backwards to find very next operand with isDef set. If instruction + // is the Def, then the DebugValue is assotiated with it. + bool FoundDef = false; + for (MachineBasicBlock::reverse_instr_iterator + I = std::next(MI->getReverseIterator()), + E = MBB.instr_rend(); + I != E; ++I) { + if (Defs.find(&*I) == Defs.end()) + continue; + FoundDef = &*I == Def; + break; + } + if (FoundDef) { + // Record all operands and instructions related to the Def. + Operands.push_back(&Op); + if (Instrs.find(MI) == Instrs.end()) + Instrs.insert(MI); + } + } } -} -static void UpdateDebugValuesReg(unsigned Reg, unsigned NewReg, - MachineBasicBlock &MBB, - MachineRegisterInfo &MRI) { - for (auto &Op : MRI.reg_operands(Reg)) { - MachineInstr *MI = Op.getParent(); - assert(MI != nullptr); - if (MI->isDebugValue() && MI->getParent() == &MBB) - Op.setReg(NewReg); + void move(MachineInstr *Insert, MachineBasicBlock &MBB) { + for (MachineInstr *MI : Instrs) { + MBB.splice(Insert, OpMBB, MI); + LLVM_DEBUG(dbgs() << " - - Moved with DBG_VALUE: "; MI->dump()); + } + OpMBB = &MBB; + } + + void updateReg(unsigned NewReg) { + for (MachineOperand *Op : Operands) + Op->setReg(NewReg); + OpReg = NewReg; + LLVM_DEBUG(for (MachineInstr *MI + : Instrs) { + dbgs() << " - - Moved with DBG_VALUE: "; + MI->dump(); + }); + } + + void clone(MachineInstr *Insert, MachineBasicBlock &MBB, unsigned NewReg, + const WebAssemblyInstrInfo *TII) { + for (MachineInstr *MI : Instrs) { + MachineInstr &Clone = TII->duplicate(MBB, Insert, *MI); + for (unsigned I = 0, E = Clone.getNumOperands(); I != E; ++I) { + MachineOperand &MO = Clone.getOperand(I); + if (MO.isReg() && MO.getReg() == OpReg) + MO.setReg(NewReg); + } + LLVM_DEBUG(dbgs() << " - - Cloned DBG_VALUE: "; Clone.dump()); + } } -} +}; /// A single-use def in the same block with no intervening memory or register /// dependencies; move the def down and nest it with the current instruction. @@ -504,8 +559,9 @@ MachineRegisterInfo &MRI) { LLVM_DEBUG(dbgs() << "Move for single use: "; Def->dump()); + AttachedDebugValues DefDVs(Reg, Def, MBB, MRI); MBB.splice(Insert, &MBB, Def); - MoveDebugValues(Reg, Insert, MBB, MRI); + DefDVs.move(Insert, MBB); LIS.handleMove(*Def); if (MRI.hasOneDef(Reg) && MRI.hasOneUse(Reg)) { @@ -530,7 +586,7 @@ MFI.stackifyVReg(NewReg); - UpdateDebugValuesReg(Reg, NewReg, MBB, MRI); + DefDVs.updateReg(NewReg); LLVM_DEBUG(dbgs() << " - Replaced register: "; Def->dump()); } @@ -539,29 +595,6 @@ return Def; } -static void CloneDebugValues(unsigned Reg, MachineInstr *Insert, - unsigned TargetReg, MachineBasicBlock &MBB, - MachineRegisterInfo &MRI, - const WebAssemblyInstrInfo *TII) { - SmallPtrSet Instrs; - for (auto &Op : MRI.reg_operands(Reg)) { - MachineInstr *MI = Op.getParent(); - assert(MI != nullptr); - if (MI->isDebugValue() && MI->getParent() == &MBB && - Instrs.find(MI) == Instrs.end()) - Instrs.insert(MI); - } - for (const auto &MI : Instrs) { - MachineInstr &Clone = TII->duplicate(MBB, Insert, *MI); - for (unsigned i = 0, e = Clone.getNumOperands(); i != e; ++i) { - MachineOperand &MO = Clone.getOperand(i); - if (MO.isReg() && MO.getReg() == Reg) - MO.setReg(TargetReg); - } - LLVM_DEBUG(dbgs() << " - - Cloned DBG_VALUE: "; Clone.dump()); - } -} - /// A trivially cloneable instruction; clone it and nest the new copy with the /// current instruction. static MachineInstr *RematerializeCheapDef( @@ -572,6 +605,8 @@ LLVM_DEBUG(dbgs() << "Rematerializing cheap def: "; Def.dump()); LLVM_DEBUG(dbgs() << " - for use in "; Op.getParent()->dump()); + AttachedDebugValues DefDVs(Reg, &Def, MBB, MRI); + unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(Reg)); TII->reMaterialize(MBB, Insert, NewReg, 0, Def, *TRI); Op.setReg(NewReg); @@ -601,10 +636,10 @@ LIS.RemoveMachineInstrFromMaps(Def); Def.eraseFromParent(); - MoveDebugValues(Reg, &*Insert, MBB, MRI); - UpdateDebugValuesReg(Reg, NewReg, MBB, MRI); + DefDVs.move(&*Insert, MBB); + DefDVs.updateReg(NewReg); } else { - CloneDebugValues(Reg, &*Insert, NewReg, MBB, MRI, TII); + DefDVs.clone(&*Insert, MBB, NewReg, TII); } return Clone; @@ -636,6 +671,8 @@ MachineRegisterInfo &MRI, const WebAssemblyInstrInfo *TII) { LLVM_DEBUG(dbgs() << "Move and tee for multi-use:"; Def->dump()); + AttachedDebugValues DefDVs(Reg, Def, MBB, MRI); + // Move Def into place. MBB.splice(Insert, &MBB, Def); LIS.handleMove(*Def); @@ -654,7 +691,7 @@ SlotIndex TeeIdx = LIS.InsertMachineInstrInMaps(*Tee).getRegSlot(); SlotIndex DefIdx = LIS.getInstructionIndex(*Def).getRegSlot(); - MoveDebugValues(Reg, Insert, MBB, MRI); + DefDVs.move(Insert, MBB); // Tell LiveIntervals we moved the original vreg def from Def to Tee. LiveInterval &LI = LIS.getInterval(Reg); @@ -672,8 +709,8 @@ ImposeStackOrdering(Def); ImposeStackOrdering(Tee); - CloneDebugValues(Reg, Tee, DefReg, MBB, MRI, TII); - CloneDebugValues(Reg, Insert, TeeReg, MBB, MRI, TII); + DefDVs.clone(Tee, MBB, DefReg, TII); + DefDVs.clone(Insert, MBB, TeeReg, TII); LLVM_DEBUG(dbgs() << " - Replaced register: "; Def->dump()); LLVM_DEBUG(dbgs() << " - Tee instruction: "; Tee->dump()); Index: test/DebugInfo/WebAssembly/dbg-value-move-reg-stackify.mir =================================================================== --- /dev/null +++ test/DebugInfo/WebAssembly/dbg-value-move-reg-stackify.mir @@ -0,0 +1,57 @@ +# RUN: llc < %s -run-pass=wasm-reg-stackify -x=mir 2>&1 | FileCheck %s + +# CHECK: body: +# CHECK: %1:i32 = CALL_I32 @bar, +# CHECK: DBG_VALUE %1, +# CHECK: %2:i32 = CALL_I32 @bar, +# CHECK: DBG_VALUE %2, + +--- | + target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" + target triple = "wasm32-unknown-unknown" + + declare void @foo(i32) + declare i32 @bar() + + define void @test(i64 %arg) { + unreachable + } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!4} + !0 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !2, producer: "clang LLVM (rustc version 1.30.0-dev)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !1, globals: !1) + !1 = !{} + !2 = !DIFile(filename: "", directory: "") + !3 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "&str", file: !2, size: 64, align: 32, elements: !{}, identifier: "111094d970b097647de579f9c509ef08") + !4 = !{i32 2, !"Debug Info Version", i32 3} + !5 = distinct !DILexicalBlock(scope: !6, file: !2, line: 357, column: 8) + !6 = distinct !DISubprogram(name: "testfoo", linkageName: "_testba", scope: !7, file: !2, line: 353, type: !8, isLocal: true, isDefinition: true, scopeLine: 353, flags: DIFlagPrototyped, isOptimized: true, unit: !0, templateParams: !1, retainedNodes: !9) + !7 = !DINamespace(name: "ptr", scope: null) + !8 = !DISubroutineType(types: !1) + !9 = !{!10} + !10 = !DILocalVariable(name: "val0", scope: !5, file: !2, line: 357, type: !3, align: 4) + !11 = !DILocalVariable(name: "val1", scope: !5, file: !2, line: 358, type: !3, align: 4) + !12 = !DILocalVariable(name: "val2", scope: !5, file: !2, line: 359, type: !3, align: 4) + !13 = !DILocation(line: 357, column: 12, scope: !5) + !14 = !DILocation(line: 358, column: 12, scope: !5) + !15 = !DILocation(line: 359, column: 12, scope: !5) + +--- +name: test +liveins: + - { reg: '$arguments' } +tracksRegLiveness: true +body: | + bb.0: + liveins: $arguments + %0:i64 = ARGUMENT_i64 0, implicit $arguments + %1:i32 = I32_WRAP_I64 %0:i64, implicit-def dead $arguments + DBG_VALUE %1:i32, $noreg, !10, !DIExpression(), debug-location !13; :357:12 line no:357 + %1:i32 = CALL_I32 @bar, implicit-def dead $arguments, implicit $sp32, implicit $sp64 + DBG_VALUE %1:i32, $noreg, !11, !DIExpression(), debug-location !14; :357:12 line no:357 + %1:i32 = CALL_I32 @bar, implicit-def dead $arguments, implicit $sp32, implicit $sp64 + DBG_VALUE %1:i32, $noreg, !12, !DIExpression(), debug-location !15; :357:12 line no:357 + CALL_VOID @foo, %1:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64 + RETURN_VOID implicit-def dead $arguments + +...