[llvm] r261579 - [WebAssembly] Fix writeback of stack pointer with dynamic alloca

Derek Schuff via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 22 13:57:19 PST 2016


Author: dschuff
Date: Mon Feb 22 15:57:17 2016
New Revision: 261579

URL: http://llvm.org/viewvc/llvm-project?rev=261579&view=rev
Log:
[WebAssembly] Fix writeback of stack pointer with dynamic alloca

Previously the stack pointer was only written back to memory in the
prolog. But this is wrong for dynamic allocas, for which
target-independent codegen handles SP updates after the prolog (and
possibly even in another BB). Instead update the SP global in
ADJCALLSTACKDOWN which is generated after the SP update sequence.
This will have further refinements when we add red zone support.

Modified:
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
    llvm/trunk/test/CodeGen/WebAssembly/userstack.ll

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp?rev=261579&r1=261578&r2=261579&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp Mon Feb 22 15:57:17 2016
@@ -59,12 +59,39 @@ bool WebAssemblyFrameLowering::hasReserv
   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::emitProlo
             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::emitEpilo
     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);
 }

Modified: llvm/trunk/test/CodeGen/WebAssembly/userstack.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/userstack.ll?rev=261579&r1=261578&r2=261579&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/userstack.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/userstack.ll Mon Feb 22 15:57:17 2016
@@ -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 %
  ; 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 at FUNCTION, [[FP]]
 ; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer
 ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L6]]), [[FP]]




More information about the llvm-commits mailing list