[WebAssembly] Support combining GEP and FrameIndex offsets in memory operand offset...
authorDerek Schuff <dschuff@google.com>
Thu, 7 Jan 2016 18:55:52 +0000 (18:55 +0000)
committerDerek Schuff <dschuff@google.com>
Thu, 7 Jan 2016 18:55:52 +0000 (18:55 +0000)
Previously we only supported putting the FI into memory operand offset
fields if there was nothing there already. Now combine them.

Differential Revision: http://reviews.llvm.org/D15941

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

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

index dcada45..90d8dda 100644 (file)
@@ -61,17 +61,23 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
   MachineFunction &MF = *MBB.getParent();
   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
   const MachineFrameInfo& MFI = *MF.getFrameInfo();
-  int FrameOffset = MFI.getStackSize() + MFI.getObjectOffset(FrameIndex);
+  int64_t FrameOffset = MFI.getStackSize() + MFI.getObjectOffset(FrameIndex);
 
   if (MI.mayLoadOrStore()) {
     // If this is a load or store, make it relative to SP and fold the frame
-    // offset directly in
-    assert(MI.getOperand(1).getImm() == 0 &&
-           "Can't eliminate FI yet if offset is already set");
-    MI.getOperand(1).setImm(FrameOffset);
+    // offset directly in.
+    assert(FrameOffset >= 0 && MI.getOperand(1).getImm() >= 0);
+    int64_t Offset = MI.getOperand(1).getImm() + FrameOffset;
+
+    if (static_cast<uint64_t>(Offset) > std::numeric_limits<uint32_t>::max()) {
+      // If this happens the program is invalid, but better to error here than
+      // generate broken code.
+      report_fatal_error("Memory offset field overflow");
+    }
+    MI.getOperand(1).setImm(Offset);
     MI.getOperand(2).ChangeToRegister(WebAssembly::SP32, /*IsDef=*/false);
   } else {
-    // Otherwise create an i32.add SP, offset and make it the operand
+    // Otherwise create an i32.add SP, offset and make it the operand.
     auto &MRI = MF.getRegInfo();
     const auto *TII = MF.getSubtarget().getInstrInfo();
 
index d102e02..cc50192 100644 (file)
@@ -72,6 +72,27 @@ define void @allocarray() {
  ret void
 }
 
+define void @allocarray_inbounds() {
+ ; CHECK: i32.const [[L1:.+]]=, __stack_pointer
+ ; CHECK-NEXT: i32.load [[L1]]=, 0([[L1]])
+ ; CHECK-NEXT: i32.const [[L2:.+]]=, 32
+ ; CHECK-NEXT: i32.sub [[SP:.+]]=, [[L1]], [[L2]]
+ %r = alloca [5 x i32]
+ ; CHECK: i32.const $push[[L3:.+]]=, 1
+ ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]]
+ %p = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 0
+ store i32 1, i32* %p
+ ; This store should have both the GEP and the FI folded into it.
+ ; CHECK-NEXT: i32.store {{.*}}=, 16([[SP]]), $pop
+ %p2 = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 1
+ store i32 1, i32* %p2
+ ; CHECK: i32.const [[L7:.+]]=, 32
+ ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], [[L7]]
+ ; CHECK-NEXT: i32.const [[L8:.+]]=, __stack_pointer
+ ; CHECK-NEXT: i32.store [[SP]]=, 0([[L7]]), [[SP]]
+ ret void
+}
+
 define void @dynamic_alloca(i32 %alloc) {
  ; TODO: Support frame pointers
  ;%r = alloca i32, i32 %alloc