diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp | 89 |
1 files changed, 50 insertions, 39 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp index acbd4c9921b0..55925bcbe771 100644 --- a/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp +++ b/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp @@ -31,16 +31,6 @@ using namespace llvm; #define DEBUG_TYPE "wasm-explicit-locals" -// A command-line option to disable this pass, and keep implicit locals -// for the purpose of testing with lit/llc ONLY. -// This produces output which is not valid WebAssembly, and is not supported -// by assemblers/disassemblers and other MC based tools. -static cl::opt<bool> WasmDisableExplicitLocals( - "wasm-disable-explicit-locals", cl::Hidden, - cl::desc("WebAssembly: output implicit locals in" - " instruction output for test purposes only."), - cl::init(false)); - namespace { class WebAssemblyExplicitLocals final : public MachineFunctionPass { StringRef getPassName() const override { @@ -69,13 +59,28 @@ FunctionPass *llvm::createWebAssemblyExplicitLocals() { return new WebAssemblyExplicitLocals(); } +static void checkFrameBase(WebAssemblyFunctionInfo &MFI, unsigned Local, + unsigned Reg) { + // Mark a local for the frame base vreg. + if (MFI.isFrameBaseVirtual() && Reg == MFI.getFrameBaseVreg()) { + LLVM_DEBUG({ + dbgs() << "Allocating local " << Local << "for VReg " + << Register::virtReg2Index(Reg) << '\n'; + }); + MFI.setFrameBaseLocal(Local); + } +} + /// Return a local id number for the given register, assigning it a new one /// if it doesn't yet have one. static unsigned getLocalId(DenseMap<unsigned, unsigned> &Reg2Local, - unsigned &CurLocal, unsigned Reg) { + WebAssemblyFunctionInfo &MFI, unsigned &CurLocal, + unsigned Reg) { auto P = Reg2Local.insert(std::make_pair(Reg, CurLocal)); - if (P.second) + if (P.second) { + checkFrameBase(MFI, CurLocal, Reg); ++CurLocal; + } return P.first->second; } @@ -168,11 +173,18 @@ static MVT typeForRegClass(const TargetRegisterClass *RC) { /// start of the expression tree. static MachineInstr *findStartOfTree(MachineOperand &MO, MachineRegisterInfo &MRI, - WebAssemblyFunctionInfo &MFI) { + const WebAssemblyFunctionInfo &MFI) { Register Reg = MO.getReg(); assert(MFI.isVRegStackified(Reg)); MachineInstr *Def = MRI.getVRegDef(Reg); + // If this instruction has any non-stackified defs, it is the start + for (auto DefReg : Def->defs()) { + if (!MFI.isVRegStackified(DefReg.getReg())) { + return Def; + } + } + // Find the first stackified use and proceed from there. for (MachineOperand &DefMO : Def->explicit_uses()) { if (!DefMO.isReg()) @@ -189,10 +201,6 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { "********** Function: " << MF.getName() << '\n'); - // Disable this pass if directed to do so. - if (WasmDisableExplicitLocals) - return false; - bool Changed = false; MachineRegisterInfo &MRI = MF.getRegInfo(); WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); @@ -210,7 +218,9 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { break; Register Reg = MI.getOperand(0).getReg(); assert(!MFI.isVRegStackified(Reg)); - Reg2Local[Reg] = static_cast<unsigned>(MI.getOperand(1).getImm()); + auto Local = static_cast<unsigned>(MI.getOperand(1).getImm()); + Reg2Local[Reg] = Local; + checkFrameBase(MFI, Local, Reg); MI.eraseFromParent(); Changed = true; } @@ -233,6 +243,12 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { if (MI.isDebugInstr() || MI.isLabel()) continue; + if (MI.getOpcode() == WebAssembly::IMPLICIT_DEF) { + MI.eraseFromParent(); + Changed = true; + continue; + } + // Replace tee instructions with local.tee. The difference is that tee // instructions have two defs, while local.tee instructions have one def // and an index of a local to write to. @@ -244,18 +260,18 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { // Stackify the input if it isn't stackified yet. if (!MFI.isVRegStackified(OldReg)) { - unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg); + unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg); Register NewReg = MRI.createVirtualRegister(RC); unsigned Opc = getLocalGetOpcode(RC); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(Opc), NewReg) .addImm(LocalId); MI.getOperand(2).setReg(NewReg); - MFI.stackifyVReg(NewReg); + MFI.stackifyVReg(MRI, NewReg); } // Replace the TEE with a LOCAL_TEE. unsigned LocalId = - getLocalId(Reg2Local, CurLocal, MI.getOperand(1).getReg()); + getLocalId(Reg2Local, MFI, CurLocal, MI.getOperand(1).getReg()); unsigned Opc = getLocalTeeOpcode(RC); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(Opc), MI.getOperand(0).getReg()) @@ -269,20 +285,13 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { continue; } - // Insert local.sets for any defs that aren't stackified yet. Currently - // we handle at most one def. - assert(MI.getDesc().getNumDefs() <= 1); - if (MI.getDesc().getNumDefs() == 1) { - Register OldReg = MI.getOperand(0).getReg(); + // Insert local.sets for any defs that aren't stackified yet. + for (auto &Def : MI.defs()) { + Register OldReg = Def.getReg(); if (!MFI.isVRegStackified(OldReg)) { const TargetRegisterClass *RC = MRI.getRegClass(OldReg); Register NewReg = MRI.createVirtualRegister(RC); auto InsertPt = std::next(MI.getIterator()); - if (MI.getOpcode() == WebAssembly::IMPLICIT_DEF) { - MI.eraseFromParent(); - Changed = true; - continue; - } if (UseEmpty[Register::virtReg2Index(OldReg)]) { unsigned Opc = getDropOpcode(RC); MachineInstr *Drop = @@ -290,8 +299,10 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { .addReg(NewReg); // After the drop instruction, this reg operand will not be used Drop->getOperand(0).setIsKill(); + if (MFI.isFrameBaseVirtual() && OldReg == MFI.getFrameBaseVreg()) + MFI.clearFrameBaseVreg(); } else { - unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg); + unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg); unsigned Opc = getLocalSetOpcode(RC); WebAssemblyDebugValueManager(&MI).replaceWithLocal(LocalId); @@ -300,12 +311,12 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { .addImm(LocalId) .addReg(NewReg); } - MI.getOperand(0).setReg(NewReg); // This register operand of the original instruction is now being used // by the inserted drop or local.set instruction, so make it not dead // yet. - MI.getOperand(0).setIsDead(false); - MFI.stackifyVReg(NewReg); + Def.setReg(NewReg); + Def.setIsDead(false); + MFI.stackifyVReg(MRI, NewReg); Changed = true; } } @@ -323,7 +334,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { // immediates. if (MO.isDef()) { assert(MI.isInlineAsm()); - unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg); + unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg); // If this register operand is tied to another operand, we can't // change it to an immediate. Untie it first. MI.untieRegOperand(MI.getOperandNo(&MO)); @@ -341,7 +352,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { // Our contract with inline asm register operands is to provide local // indices as immediates. if (MI.isInlineAsm()) { - unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg); + unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg); // Untie it first if this reg operand is tied to another operand. MI.untieRegOperand(MI.getOperandNo(&MO)); MO.ChangeToImmediate(LocalId); @@ -349,7 +360,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { } // Insert a local.get. - unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg); + unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg); const TargetRegisterClass *RC = MRI.getRegClass(OldReg); Register NewReg = MRI.createVirtualRegister(RC); unsigned Opc = getLocalGetOpcode(RC); @@ -357,7 +368,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { BuildMI(MBB, InsertPt, MI.getDebugLoc(), TII->get(Opc), NewReg) .addImm(LocalId); MO.setReg(NewReg); - MFI.stackifyVReg(NewReg); + MFI.stackifyVReg(MRI, NewReg); Changed = true; } |