diff options
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp')
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | 65 |
1 files changed, 62 insertions, 3 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp index ddf2d8b..8cbfc98 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -733,12 +733,30 @@ void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) { } } +// Get the appropriate copy opcode for the given register class. +static unsigned getCopyOpcode(const TargetRegisterClass *RC) { + if (RC == &WebAssembly::I32RegClass) + return WebAssembly::COPY_I32; + if (RC == &WebAssembly::I64RegClass) + return WebAssembly::COPY_I64; + if (RC == &WebAssembly::F32RegClass) + return WebAssembly::COPY_F32; + if (RC == &WebAssembly::F64RegClass) + return WebAssembly::COPY_F64; + if (RC == &WebAssembly::V128RegClass) + return WebAssembly::COPY_V128; + if (RC == &WebAssembly::EXNREFRegClass) + return WebAssembly::COPY_EXNREF; + llvm_unreachable("Unexpected register class"); +} + // When MBB is split into MBB and Split, we should unstackify defs in MBB that // have their uses in Split. static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB, MachineBasicBlock &Split, WebAssemblyFunctionInfo &MFI, - MachineRegisterInfo &MRI) { + MachineRegisterInfo &MRI, + const WebAssemblyInstrInfo &TII) { for (auto &MI : Split) { for (auto &MO : MI.explicit_uses()) { if (!MO.isReg() || Register::isPhysicalRegister(MO.getReg())) @@ -748,6 +766,47 @@ static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB, MFI.unstackifyVReg(MO.getReg()); } } + + // In RegStackify, when a register definition is used multiple times, + // Reg = INST ... + // INST ..., Reg, ... + // INST ..., Reg, ... + // INST ..., Reg, ... + // + // we introduce a TEE, which has the following form: + // DefReg = INST ... + // TeeReg, Reg = TEE_... DefReg + // INST ..., TeeReg, ... + // INST ..., Reg, ... + // INST ..., Reg, ... + // with DefReg and TeeReg stackified but Reg not stackified. + // + // But the invariant that TeeReg should be stackified can be violated while we + // unstackify registers in the split BB above. In this case, we convert TEEs + // into two COPYs. This COPY will be eventually eliminated in ExplicitLocals. + // DefReg = INST ... + // TeeReg = COPY DefReg + // Reg = COPY DefReg + // INST ..., TeeReg, ... + // INST ..., Reg, ... + // INST ..., Reg, ... + for (auto I = MBB.begin(), E = MBB.end(); I != E;) { + MachineInstr &MI = *I++; + if (!WebAssembly::isTee(MI.getOpcode())) + continue; + Register TeeReg = MI.getOperand(0).getReg(); + Register Reg = MI.getOperand(1).getReg(); + Register DefReg = MI.getOperand(2).getReg(); + if (!MFI.isVRegStackified(TeeReg)) { + // Now we are not using TEE anymore, so unstackify DefReg too + MFI.unstackifyVReg(DefReg); + unsigned CopyOpc = getCopyOpcode(MRI.getRegClass(DefReg)); + BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), TeeReg) + .addReg(DefReg); + BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), Reg).addReg(DefReg); + MI.eraseFromParent(); + } + } } bool WebAssemblyCFGStackify::fixUnwindMismatches(MachineFunction &MF) { @@ -1068,7 +1127,7 @@ bool WebAssemblyCFGStackify::fixUnwindMismatches(MachineFunction &MF) { BrDest->insert(BrDest->end(), EndTry->removeFromParent()); // Take out the handler body from EH pad to the new branch destination BB. BrDest->splice(BrDest->end(), EHPad, SplitPos, EHPad->end()); - unstackifyVRegsUsedInSplitBB(*EHPad, *BrDest, MFI, MRI); + unstackifyVRegsUsedInSplitBB(*EHPad, *BrDest, MFI, MRI, TII); // Fix predecessor-successor relationship. BrDest->transferSuccessors(EHPad); EHPad->addSuccessor(BrDest); @@ -1206,7 +1265,7 @@ bool WebAssemblyCFGStackify::fixUnwindMismatches(MachineFunction &MF) { // new nested continuation BB. NestedCont->splice(NestedCont->end(), MBB, std::next(RangeEnd->getIterator()), MBB->end()); - unstackifyVRegsUsedInSplitBB(*MBB, *NestedCont, MFI, MRI); + unstackifyVRegsUsedInSplitBB(*MBB, *NestedCont, MFI, MRI, TII); registerTryScope(NestedTry, NestedEndTry, NestedEHPad); // Fix predecessor-successor relationship. |