summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp67
-rw-r--r--llvm/test/CodeGen/WebAssembly/userstack.ll17
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]]
OpenPOWER on IntegriCloud