]> granicus.if.org Git - llvm/commitdiff
[WebAssembly] Use the frame pointer instead of the stack pointer
authorDerek Schuff <dschuff@google.com>
Mon, 26 Sep 2016 21:18:03 +0000 (21:18 +0000)
committerDerek Schuff <dschuff@google.com>
Mon, 26 Sep 2016 21:18:03 +0000 (21:18 +0000)
When we have dynamic allocas we have a frame pointer, and
when we're lowering frame indexes we should make sure we use it.

Patch by Jacob Gravelle

Differential Revision: https://reviews.llvm.org/D24889

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282442 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
test/CodeGen/WebAssembly/userstack.ll

index 5e5b288f2e73f270111be81fe34301b36c3e38c5..bb8fe9ae99696995346a8e46d0f7cb38d59309bb 100644 (file)
@@ -64,6 +64,11 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
   const MachineFrameInfo &MFI = MF.getFrameInfo();
   int64_t FrameOffset = MFI.getStackSize() + MFI.getObjectOffset(FrameIndex);
 
+  assert(MFI.getObjectSize(FrameIndex) != 0 &&
+         "We assume that variable-sized objects have already been lowered, "
+         "and don't use FrameIndex operands.");
+  unsigned FrameRegister = getFrameRegister(MF);
+
   // If this is the address operand of a load or store, make it relative to SP
   // and fold the frame offset directly in.
   if (MI.mayLoadOrStore() && FIOperandNum == WebAssembly::MemOpAddressOperandNo) {
@@ -73,7 +78,7 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
     if (static_cast<uint64_t>(Offset) <= std::numeric_limits<uint32_t>::max()) {
       MI.getOperand(FIOperandNum - 1).setImm(Offset);
       MI.getOperand(FIOperandNum)
-          .ChangeToRegister(WebAssembly::SP32, /*IsDef=*/false);
+          .ChangeToRegister(FrameRegister, /*IsDef=*/false);
       return;
     }
   }
@@ -94,7 +99,7 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
           MachineOperand &ImmMO = Def->getOperand(1);
           ImmMO.setImm(ImmMO.getImm() + uint32_t(FrameOffset));
           MI.getOperand(FIOperandNum)
-              .ChangeToRegister(WebAssembly::SP32, /*IsDef=*/false);
+              .ChangeToRegister(FrameRegister, /*IsDef=*/false);
           return;
         }
       }
@@ -104,7 +109,7 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
   // Otherwise create an i32.add SP, offset and make it the operand.
   const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
 
-  unsigned FIRegOperand = WebAssembly::SP32;
+  unsigned FIRegOperand = FrameRegister;
   if (FrameOffset) {
     // Create i32.add SP, offset and make it the operand.
     const TargetRegisterClass *PtrRC =
@@ -116,7 +121,7 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
     FIRegOperand = MRI.createVirtualRegister(PtrRC);
     BuildMI(MBB, *II, II->getDebugLoc(), TII->get(WebAssembly::ADD_I32),
             FIRegOperand)
-        .addReg(WebAssembly::SP32)
+        .addReg(FrameRegister)
         .addReg(OffsetOp);
   }
   MI.getOperand(FIOperandNum).ChangeToRegister(FIRegOperand, /*IsDef=*/false);
index c87be7326caba6ab84d13c591b97a05d0ca843aa..234e647f196298b6f6c05681320a2c431657f7d7 100644 (file)
@@ -173,21 +173,62 @@ define void @dynamic_alloca_redzone(i32 %alloc) {
 ; CHECK-LABEL: dynamic_static_alloca:
 define void @dynamic_static_alloca(i32 %alloc) noredzone {
  ; Decrement SP in the prolog by the static amount and writeback to memory.
- ; CHECK: i32.const $push[[L11:.+]]=, 0{{$}}
- ; CHECK: i32.const $push[[L8:.+]]=, 0{{$}}
- ; CHECK-NEXT: i32.load $push[[L9:.+]]=, __stack_pointer($pop[[L8]])
- ; CHECK-NEXT: i32.const $push[[L10:.+]]=, 16
- ; CHECK-NEXT: i32.sub $push[[L20:.+]]=, $pop[[L9]], $pop[[L10]]
- ; CHECK-NEXT: tee_local $push[[L19:.+]]=, $[[FP:.+]]=, $pop[[L20]]
- ; CHECK:      i32.store $drop=, __stack_pointer($pop{{.+}}), $pop{{.+}}
+ ; CHECK: i32.const $push[[L13:.+]]=, 0{{$}}
+ ; CHECK: i32.const $push[[L10:.+]]=, 0{{$}}
+ ; CHECK-NEXT: i32.load $push[[L11:.+]]=, __stack_pointer($pop[[L10]])
+ ; CHECK-NEXT: i32.const $push[[L12:.+]]=, 16
+ ; CHECK-NEXT: i32.sub $push[[L23:.+]]=, $pop[[L11]], $pop[[L12]]
+ ; CHECK-NEXT: tee_local $push[[L22:.+]]=, $[[SP:.+]]=, $pop[[L23]]
+ ; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop{{.+}}), $pop[[L22]]
+
+ ; Alloc and write to a static alloca
+ ; CHECK: copy_local $push[[L21:.+]]=, $[[SP]]
+ ; CHECK-NEXT: tee_local $push[[pushedFP:.+]]=, $[[FP:.+]]=, $pop[[L21]]
+ ; CHECK-NEXT: i32.const $push[[L0:.+]]=, 101
+ ; CHECK-NEXT: i32.store $drop=, [[static_offset:.+]]($pop[[pushedFP]]), $pop[[L0]]
+ %static = alloca i32
+ store volatile i32 101, i32* %static
+
+ ; Decrement SP in the body by the dynamic amount.
+ ; CHECK: i32.sub
+ ; CHECK: tee_local $push{{.+}}=, $[[dynamic_local:.+]]=, $pop{{.+}}
+ ; CHECK: i32.store {{.*}} __stack_pointer
+ %dynamic = alloca i32, i32 %alloc
+
+ ; Ensure we don't modify the frame pointer after assigning it.
+ ; CHECK-NOT: $[[FP]]=
+
+ ; Ensure the static address doesn't change after modifying the stack pointer.
+ ; CHECK: i32.const $push[[L7:.+]]=, 102
+ ; CHECK-NEXT: i32.store $drop=, [[static_offset]]($[[FP]]), $pop[[L7]]
+ ; CHECK-NEXT: i32.const $push[[L8:.+]]=, 103
+ ; CHECK-NEXT: i32.store $drop=, 0($[[dynamic_local]]), $pop[[L8]]
+ store volatile i32 102, i32* %static
+ store volatile i32 103, i32* %dynamic
+
  ; Decrement SP in the body by the dynamic amount.
  ; CHECK: i32.sub
+ ; CHECK: tee_local $push{{.+}}=, $[[dynamic2_local:.+]]=, $pop{{.+}}
+ %dynamic.2 = alloca i32, i32 %alloc
+
+ ; CHECK-NOT: $[[FP]]=
+
+ ; Ensure neither the static nor dynamic address changes after the second
+ ; modification of the stack pointer.
+ ; CHECK: i32.const $push[[L9:.+]]=, 104
+ ; CHECK-NEXT: i32.store $drop=, [[static_offset]]($[[FP]]), $pop[[L9]]
+ ; CHECK-NEXT: i32.const $push[[L10:.+]]=, 105
+ ; CHECK-NEXT: i32.store $drop=, 0($[[dynamic_local]]), $pop[[L10]]
+ ; CHECK-NEXT: i32.const $push[[L11:.+]]=, 106
+ ; CHECK-NEXT: i32.store $drop=, 0($[[dynamic2_local]]), $pop[[L11]]
+ store volatile i32 104, i32* %static
+ store volatile i32 105, i32* %dynamic
+ store volatile i32 106, i32* %dynamic.2
+
  ; Writeback to memory.
- ; CHECK: i32.store $drop=, __stack_pointer($pop{{.+}}), $pop{{.+}}
- %r1 = alloca i32
- %r = alloca i32, i32 %alloc
- store i32 0, i32* %r
- ; CHEC: i32.store $drop=, 0($pop{{.+}}), $pop{{.+}}
+ ; CHECK: i32.const $push[[L17:.+]]=, 16
+ ; CHECK-NEXT: i32.add $push[[L18:.+]]=, $[[FP]], $pop[[L17]]
+ ; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop{{.+}}), $pop[[L18]]
  ret void
 }