diff options
| -rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp | 67 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WebAssembly/userstack.ll | 17 |
2 files changed, 47 insertions, 37 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp index cbf59d1a3ce..c5f43d806ed 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp @@ -59,12 +59,39 @@ bool WebAssemblyFrameLowering::hasReservedCallFrame( return !MF.getFrameInfo()->hasVarSizedObjects(); } +static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator &InsertPt, + DebugLoc DL) { + auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer"); + unsigned SPAddr = + MF.getRegInfo().createVirtualRegister(&WebAssembly::I32RegClass); + const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); + + BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), SPAddr) + .addExternalSymbol(SPSymbol); + auto *MMO = new MachineMemOperand(MachinePointerInfo(), + MachineMemOperand::MOStore, 4, 4); + BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::STORE_I32), + WebAssembly::SP32) + .addImm(0) + .addReg(SPAddr) + .addImm(2) // p2align + .addReg(SrcReg) + .addMemOperand(MMO); + MF.getInfo<WebAssemblyFunctionInfo>()->stackifyVReg(SPAddr); +} + void WebAssemblyFrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { - // TODO: can we avoid using call frame pseudos altogether? - assert(!I->getOperand(0).getImm() && - "Stack should not be adjusted around calls"); + assert(!I->getOperand(0).getImm() && hasFP(MF) && + "Call frame pseudos should only be used for dynamic stack adjustment"); + const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); + if (I->getOpcode() == TII->getCallFrameDestroyOpcode()) { + DebugLoc DL = I->getDebugLoc(); + writeSPToMemory(WebAssembly::SP32, MF, MBB, I, DL); + } MBB.erase(I); } @@ -125,21 +152,8 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF, WebAssembly::FP32) .addReg(WebAssembly::SP32); } - if (StackSize || hasFP(MF)) { - SPAddr = MRI.createVirtualRegister(&WebAssembly::I32RegClass); - // The SP32 register now has the new stacktop. Also write it back to memory. - BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), SPAddr) - .addExternalSymbol(SPSymbol); - auto *MMO = new MachineMemOperand(MachinePointerInfo(), - MachineMemOperand::MOStore, 4, 4); - BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::STORE_I32), - WebAssembly::SP32) - .addImm(0) - .addReg(SPAddr) - .addImm(2) // p2align - .addReg(WebAssembly::SP32) - .addMemOperand(MMO); - WFI->stackifyVReg(SPAddr); + if (StackSize) { + writeSPToMemory(WebAssembly::SP32, MF, MBB, InsertPt, DL); } } @@ -171,18 +185,7 @@ void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF, WFI->stackifyVReg(OffsetReg); } - auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer"); - unsigned SPAddr = MRI.createVirtualRegister(&WebAssembly::I32RegClass); - BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), SPAddr) - .addExternalSymbol(SPSymbol); - auto *MMO = new MachineMemOperand(MachinePointerInfo(), - MachineMemOperand::MOStore, 4, 4); - BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::STORE_I32), - WebAssembly::SP32) - .addImm(0) - .addReg(SPAddr) - .addImm(2) // p2align - .addReg((!StackSize && hasFP(MF)) ? WebAssembly::FP32 : WebAssembly::SP32) - .addMemOperand(MMO); - WFI->stackifyVReg(SPAddr); + writeSPToMemory( + (!StackSize && hasFP(MF)) ? WebAssembly::FP32 : WebAssembly::SP32, MF, + MBB, InsertPt, DL); } diff --git a/llvm/test/CodeGen/WebAssembly/userstack.ll b/llvm/test/CodeGen/WebAssembly/userstack.ll index 1b9807399a8..74edd89323a 100644 --- a/llvm/test/CodeGen/WebAssembly/userstack.ll +++ b/llvm/test/CodeGen/WebAssembly/userstack.ll @@ -134,8 +134,11 @@ define void @dynamic_alloca(i32 %alloc) { ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer ; CHECK-NEXT: i32.load [[SP:.+]]=, 0($pop[[L1]]) ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]] - ; Target independent codegen bumps the stack pointer - ; CHECK: i32.const $push[[L4:.+]]=, __stack_pointer{{$}} + ; Target independent codegen bumps the stack pointer. + ; CHECK: i32.sub + ; CHECK-NEXT: copy_local [[SP]]=, + ; Check that SP is written back to memory after decrement + ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer{{$}} ; CHECK-NEXT: i32.store $discard=, 0($pop[[L4]]), [[SP]] %r = alloca i32, i32 %alloc ; Target-independent codegen also calculates the store addr @@ -145,9 +148,9 @@ define void @dynamic_alloca(i32 %alloc) { ret void } - ; CHECK-LABEL: dynamic_static_alloca: define void @dynamic_static_alloca(i32 %alloc) { + ; Decrement SP in the prolog by the static amount and writeback to memory. ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]]) ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16 @@ -155,6 +158,12 @@ define void @dynamic_static_alloca(i32 %alloc) { ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]] ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer ; CHECK-NEXT: i32.store {{.*}}=, 0($pop[[L4]]), [[SP]] + ; Decrement SP in the body by the dynamic amount. + ; CHECK: i32.sub + ; CHECK: copy_local [[SP]]=, + ; Writeback to memory. + ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.store {{.*}}=, 0($pop[[L4]]), [[SP]] %r1 = alloca i32 %r = alloca i32, i32 %alloc store i32 0, i32* %r @@ -194,8 +203,6 @@ declare i8* @llvm.frameaddress(i32) ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer ; CHECK-NEXT: i32.load [[SP:.+]]=, 0($pop[[L1]]) ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]] -; CHECK-NEXT: i32.const $push[[L2:.+]]=, __stack_pointer{{$}} -; CHECK-NEXT: i32.store $discard=, 0($pop[[L2]]), [[SP]] ; CHECK-NEXT: call use_i8_star@FUNCTION, [[FP]] ; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L6]]), [[FP]] |

