summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@google.com>2016-01-07 18:55:52 +0000
committerDerek Schuff <dschuff@google.com>2016-01-07 18:55:52 +0000
commit9bfea27c263e03e57a6dc639786fa356652bd5c6 (patch)
tree2dd0bab32def685f14130960d27b2ca4f2b629d7
parenta4730cf0b411dc58839ddaea79de05e20236d754 (diff)
downloadbcm5719-llvm-9bfea27c263e03e57a6dc639786fa356652bd5c6.tar.gz
bcm5719-llvm-9bfea27c263e03e57a6dc639786fa356652bd5c6.zip
[WebAssembly] Support combining GEP and FrameIndex offsets in memory operand offset field
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 llvm-svn: 257084
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp18
-rw-r--r--llvm/test/CodeGen/WebAssembly/userstack.ll21
2 files changed, 33 insertions, 6 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
index dcada45f96d..90d8dda530b 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
@@ -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();
diff --git a/llvm/test/CodeGen/WebAssembly/userstack.ll b/llvm/test/CodeGen/WebAssembly/userstack.ll
index d102e025128..cc50192b66d 100644
--- a/llvm/test/CodeGen/WebAssembly/userstack.ll
+++ b/llvm/test/CodeGen/WebAssembly/userstack.ll
@@ -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
OpenPOWER on IntegriCloud