Skip to content

Commit

Permalink
[WebAssembly] Put __stack_pointer in the offset field of loads and st…
Browse files Browse the repository at this point in the history
…ores.

Instead of this:

i32.const       $push10=, __stack_pointer
i32.load        $push11=, 0($pop10)

Emit this:

i32.const       $push10=, 0
i32.load        $push11=, __stack_pointer($pop10)

It's not currently clear which is better, though there's a chance the second
form may be better at overall compression. We can revisit this when we have
more data; for now it makes sense to make PEI consistent with isel.

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


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270635 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Dan Gohman committed May 24, 2016
1 parent b0d0618 commit 04c5ee8
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 62 deletions.
20 changes: 10 additions & 10 deletions lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,18 @@ static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF,
MachineRegisterInfo &MRI = MF.getRegInfo();
const TargetRegisterClass *PtrRC =
MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
unsigned SPAddr = MRI.createVirtualRegister(PtrRC);
unsigned Zero = MRI.createVirtualRegister(PtrRC);
unsigned Drop = MRI.createVirtualRegister(PtrRC);
const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();

BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), SPAddr)
.addExternalSymbol(SPSymbol);
BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), Zero)
.addImm(0);
auto *MMO = new MachineMemOperand(MachinePointerInfo(MF.getPSVManager()
.getExternalSymbolCallEntry(ES)),
MachineMemOperand::MOStore, 4, 4);
BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32), Drop)
.addImm(0)
.addReg(SPAddr)
.addExternalSymbol(SPSymbol)
.addReg(Zero)
.addImm(2) // p2align
.addReg(SrcReg)
.addMemOperand(MMO);
Expand Down Expand Up @@ -137,20 +137,20 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,

const TargetRegisterClass *PtrRC =
MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
unsigned SPAddr = MRI.createVirtualRegister(PtrRC);
unsigned Zero = MRI.createVirtualRegister(PtrRC);
unsigned SPReg = MRI.createVirtualRegister(PtrRC);
const char *ES = "__stack_pointer";
auto *SPSymbol = MF.createExternalSymbolName(ES);
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), SPAddr)
.addExternalSymbol(SPSymbol);
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), Zero)
.addImm(0);
auto *LoadMMO = new MachineMemOperand(MachinePointerInfo(MF.getPSVManager()
.getExternalSymbolCallEntry(ES)),
MachineMemOperand::MOLoad, 4, 4);
// Load the SP value.
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32),
StackSize ? SPReg : (unsigned)WebAssembly::SP32)
.addImm(0) // offset
.addReg(SPAddr) // addr
.addExternalSymbol(SPSymbol)
.addReg(Zero) // addr
.addImm(2) // p2align
.addMemOperand(LoadMMO);

Expand Down
22 changes: 11 additions & 11 deletions test/CodeGen/WebAssembly/byval.ll
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ declare void @ext_byval_func_empty(%EmptyStruct* byval)
; CHECK-LABEL: byval_arg
define void @byval_arg(%SmallStruct* %ptr) {
; CHECK: .param i32
; CHECK: i32.const $push[[L4:.+]]=, __stack_pointer
; CHECK: i32.const $push[[L4:.+]]=, 0
; Subtract 16 from SP (SP is 16-byte aligned)
; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
; CHECK: i32.const $push[[L1:.+]]=, 0
; CHECK-NEXT: i32.load $push[[L2:.+]]=, __stack_pointer($pop[[L1]])
; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
; CHECK-NEXT: i32.sub $push[[L10:.+]]=, $pop[[L2]], $pop[[L3]]
; Ensure SP is stored back before the call
; CHECK-NEXT: i32.store $push[[L12:.+]]=, 0($pop[[L4]]), $pop[[L10]]{{$}}
; CHECK-NEXT: i32.store $push[[L12:.+]]=, __stack_pointer($pop[[L4]]), $pop[[L10]]{{$}}
; CHECK-NEXT: tee_local $push[[L11:.+]]=, $[[SP:.+]]=, $pop[[L12]]{{$}}
; Copy the SmallStruct argument to the stack (SP+12, original SP-4)
; CHECK-NEXT: i32.load $push[[L0:.+]]=, 0($0)
Expand All @@ -41,10 +41,10 @@ define void @byval_arg(%SmallStruct* %ptr) {
; CHECK-NEXT: call ext_byval_func@FUNCTION, $pop[[ARG]]{{$}}
call void @ext_byval_func(%SmallStruct* byval %ptr)
; Restore the stack
; CHECK-NEXT: i32.const $push[[L7:.+]]=, __stack_pointer
; CHECK-NEXT: i32.const $push[[L7:.+]]=, 0
; CHECK-NEXT: i32.const $push[[L6:.+]]=, 16
; CHECK-NEXT: i32.add $push[[L8:.+]]=, $[[SP]], $pop[[L6]]
; CHECK-NEXT: i32.store {{.*}}=, 0($pop[[L7]]), $pop[[L8]]
; CHECK-NEXT: i32.store {{.*}}=, __stack_pointer($pop[[L7]]), $pop[[L8]]
; CHECK-NEXT: return
ret void
}
Expand All @@ -55,7 +55,7 @@ define void @byval_arg_align8(%SmallStruct* %ptr) {
; Don't check the entire SP sequence, just enough to get the alignment.
; CHECK: i32.const $push[[L1:.+]]=, 16
; CHECK-NEXT: i32.sub $push[[L10:.+]]=, {{.+}}, $pop[[L1]]
; CHECK-NEXT: i32.store $push[[L12:.+]]=, 0($pop{{.+}}), $pop[[L10]]{{$}}
; CHECK-NEXT: i32.store $push[[L12:.+]]=, __stack_pointer($pop{{.+}}), $pop[[L10]]{{$}}
; CHECK-NEXT: tee_local $push[[L11:.+]]=, $[[SP:.+]]=, $pop[[L12]]{{$}}
; Copy the SmallStruct argument to the stack (SP+8, original SP-8)
; CHECK-NEXT: i32.load $push[[L0:.+]]=, 0($0){{$}}
Expand Down Expand Up @@ -113,12 +113,12 @@ define void @byval_empty_callee(%EmptyStruct* byval %ptr) {

; Call memcpy for "big" byvals.
; CHECK-LABEL: big_byval:
; CHECK: i32.const $push[[L4:.+]]=, __stack_pointer
; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
; CHECK: i32.const $push[[L4:.+]]=, 0
; CHECK: i32.const $push[[L1:.+]]=, 0
; CHECK-NEXT: i32.load $push[[L2:.+]]=, __stack_pointer($pop[[L1]])
; CHECK-NEXT: i32.const $push[[L3:.+]]=, 131072
; CHECK-NEXT: i32.sub $push[[L8:.+]]=, $pop[[L2]], $pop[[L3]]
; CHECK-NEXT: i32.store $push[[L12:.+]]=, 0($pop[[L4]]), $pop[[L8]]{{$}}
; CHECK-NEXT: i32.store $push[[L12:.+]]=, __stack_pointer($pop[[L4]]), $pop[[L8]]{{$}}
; CHECK-NEXT: i32.const $push[[L0:.+]]=, 131072
; CHECK-NEXT: i32.call $push[[L11:.+]]=, memcpy@FUNCTION, $pop{{.+}}, ${{.+}}, $pop{{.+}}
; CHECK-NEXT: tee_local $push[[L9:.+]]=, $[[SP:.+]]=, $pop[[L11]]{{$}}
Expand Down
4 changes: 2 additions & 2 deletions test/CodeGen/WebAssembly/reg-stackify.ll
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,8 @@ bb10: ; preds = %bb9, %bb

; CHECK-LABEL: stackpointer_dependency:
; CHECK: call {{.+}}, stackpointer_callee@FUNCTION,
; CHECK: i32.const $push[[L0:.+]]=, __stack_pointer
; CHECK-NEXT: i32.store $drop=, 0($pop[[L0]]),
; CHECK: i32.const $push[[L0:.+]]=, 0
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L0]]),
declare i32 @stackpointer_callee(i8* readnone, i8* readnone)
declare i8* @llvm.frameaddress(i32)
define i32 @stackpointer_dependency(i8* readnone) {
Expand Down
79 changes: 40 additions & 39 deletions test/CodeGen/WebAssembly/userstack.ll
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,29 @@ declare void @ext_func_i32(i32* %ptr)
; Check that there is an extra local for the stack pointer.
; CHECK: .local i32{{$}}
define void @alloca32() noredzone {
; CHECK: i32.const $push[[L4:.+]]=, __stack_pointer{{$}}
; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer{{$}}
; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
; CHECK: i32.const $push[[L4:.+]]=, 0{{$}}
; CHECK: i32.const $push[[L1:.+]]=, 0{{$}}
; CHECK-NEXT: i32.load $push[[L2:.+]]=, __stack_pointer($pop[[L1]])
; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
; CHECK-NEXT: i32.sub $push[[L8:.+]]=, $pop[[L2]], $pop[[L3]]
; CHECK-NEXT: i32.store $push[[L10:.+]]=, 0($pop[[L4]]), $pop[[L8]]{{$}}
; CHECK-NEXT: i32.store $push[[L10:.+]]=, __stack_pointer($pop[[L4]]), $pop[[L8]]{{$}}
; CHECK-NEXT: tee_local $push[[L9:.+]]=, $[[SP:.+]]=, $pop[[L10]]{{$}}
%retval = alloca i32
; CHECK: i32.const $push[[L0:.+]]=, 0
; CHECK: i32.store {{.*}}=, 12($pop[[L9]]), $pop[[L0]]
store i32 0, i32* %retval
; CHECK: i32.const $push[[L6:.+]]=, __stack_pointer
; CHECK: i32.const $push[[L6:.+]]=, 0
; CHECK-NEXT: i32.const $push[[L5:.+]]=, 16
; CHECK-NEXT: i32.add $push[[L7:.+]]=, $[[SP]], $pop[[L5]]
; CHECK-NEXT: i32.store $drop=, 0($pop[[L6]]), $pop[[L7]]
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L6]]), $pop[[L7]]
ret void
}

; CHECK-LABEL: alloca3264:
; CHECK: .local i32{{$}}
define void @alloca3264() {
; CHECK: i32.const $push[[L2:.+]]=, __stack_pointer
; CHECK-NEXT: i32.load $push[[L3:.+]]=, 0($pop[[L2]])
; CHECK: i32.const $push[[L2:.+]]=, 0{{$}}
; CHECK-NEXT: i32.load $push[[L3:.+]]=, __stack_pointer($pop[[L2]])
; CHECK-NEXT: i32.const $push[[L4:.+]]=, 16
; CHECK-NEXT: i32.sub $push[[L6:.+]]=, $pop[[L3]], $pop[[L4]]
; CHECK-NEXT: tee_local $push[[L5:.+]]=, $[[SP:.+]]=, $pop[[L6]]
Expand All @@ -51,12 +51,12 @@ define void @alloca3264() {
; CHECK-LABEL: allocarray:
; CHECK: .local i32{{$}}
define void @allocarray() {
; CHECK: i32.const $push[[L7:.+]]=, __stack_pointer
; CHECK: i32.const $push[[L4:.+]]=, __stack_pointer
; CHECK-NEXT: i32.load $push[[L5:.+]]=, 0($pop[[L4]])
; CHECK: i32.const $push[[L7:.+]]=, 0{{$}}
; CHECK: i32.const $push[[L4:.+]]=, 0{{$}}
; CHECK-NEXT: i32.load $push[[L5:.+]]=, __stack_pointer($pop[[L4]])
; CHECK-NEXT: i32.const $push[[L6:.+]]=, 144{{$}}
; CHECK-NEXT: i32.sub $push[[L11:.+]]=, $pop[[L5]], $pop[[L6]]
; CHECK-NEXT: i32.store ${{.+}}=, 0($pop[[L7]]), $pop[[L11]]
; CHECK-NEXT: i32.store ${{.+}}=, __stack_pointer($pop[[L7]]), $pop[[L11]]
%r = alloca [33 x i32]

; CHECK: i32.const $push{{.+}}=, 24
Expand All @@ -69,10 +69,10 @@ define void @allocarray() {
%p2 = getelementptr [33 x i32], [33 x i32]* %r, i32 0, i32 3
store i32 1, i32* %p2

; CHECK: i32.const $push[[L10:.+]]=, __stack_pointer
; CHECK: i32.const $push[[L10:.+]]=, 0{{$}}
; CHECK-NEXT: i32.const $push[[L8:.+]]=, 144
; CHECK-NEXT: i32.add $push[[L19:.+]]=, $[[SP]], $pop[[L8]]
; CHECK-NEXT: i32.store $drop=, 0($pop[[L10]]), $pop[[L9]]
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L10]]), $pop[[L9]]
ret void
}

Expand Down Expand Up @@ -106,12 +106,12 @@ define void @non_mem_use(i8** %addr) {
; CHECK-LABEL: allocarray_inbounds:
; CHECK: .local i32{{$}}
define void @allocarray_inbounds() {
; CHECK: i32.const $push[[L6:.+]]=, __stack_pointer
; CHECK: i32.const $push[[L3:.+]]=, __stack_pointer
; CHECK-NEXT: i32.load $push[[L4:.+]]=, 0($pop[[L3]])
; CHECK: i32.const $push[[L6:.+]]=, 0{{$}}
; CHECK: i32.const $push[[L3:.+]]=, 0{{$}}
; CHECK-NEXT: i32.load $push[[L4:.+]]=, __stack_pointer($pop[[L3]])
; CHECK-NEXT: i32.const $push[[L5:.+]]=, 32{{$}}
; CHECK-NEXT: i32.sub $push[[L10:.+]]=, $pop[[L4]], $pop[[L5]]
; CHECK-NEXT: i32.store ${{.+}}=, 0($pop[[L6]]), $pop[[L10]]{{$}}
; CHECK-NEXT: i32.store ${{.+}}=, __stack_pointer($pop[[L6]]), $pop[[L10]]{{$}}
%r = alloca [5 x i32]
; CHECK: i32.const $push[[L3:.+]]=, 1
; CHECK-DAG: i32.store $push{{.*}}=, 24(${{.+}}), $pop[[L3]]
Expand All @@ -122,36 +122,37 @@ define void @allocarray_inbounds() {
%p2 = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 3
store i32 1, i32* %p2
call void @ext_func(i64* null);
; CHECK: i32.const $push[[L6:.+]]=, __stack_pointer
; CHECK-NEXT: i32.const $push[[L5:.+]]=, 32
; CHECK: call ext_func
; CHECK: i32.const $push[[L6:.+]]=, 0{{$}}
; CHECK-NEXT: i32.const $push[[L5:.+]]=, 32{{$}}
; CHECK-NEXT: i32.add $push[[L7:.+]]=, ${{.+}}, $pop[[L5]]
; CHECK-NEXT: i32.store $drop=, 0($pop[[L6]]), $pop[[L7]]
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L6]]), $pop[[L7]]
ret void
}

; CHECK-LABEL: dynamic_alloca:
define void @dynamic_alloca(i32 %alloc) {
; CHECK: i32.const $push[[L7:.+]]=, __stack_pointer
; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
; CHECK-NEXT: i32.load $push[[L13:.+]]=, 0($pop[[L1]])
; CHECK: i32.const $push[[L7:.+]]=, 0{{$}}
; CHECK: i32.const $push[[L1:.+]]=, 0{{$}}
; CHECK-NEXT: i32.load $push[[L13:.+]]=, __stack_pointer($pop[[L1]])
; CHECK-NEXT: tee_local $push[[L12:.+]]=, [[SP:.+]], $pop[[L13]]{{$}}
; Target independent codegen bumps the stack pointer.
; CHECK: i32.sub
; Check that SP is written back to memory after decrement
; CHECK: i32.store $drop=, 0($pop{{.+}}),
; CHECK: i32.store $drop=, __stack_pointer($pop{{.+}}),
%r = alloca i32, i32 %alloc
; Target-independent codegen also calculates the store addr
; CHECK: call ext_func_i32@FUNCTION
call void @ext_func_i32(i32* %r)
; CHECK: i32.const $push[[L3:.+]]=, __stack_pointer
; CHECK: i32.store $drop=, 0($pop[[L3]]), $pop{{.+}}
; CHECK: i32.const $push[[L3:.+]]=, 0{{$}}
; CHECK: i32.store $drop=, __stack_pointer($pop[[L3]]), $pop{{.+}}
ret void
}

; CHECK-LABEL: dynamic_alloca_redzone:
define void @dynamic_alloca_redzone(i32 %alloc) {
; CHECK: i32.const $push[[L8:.+]]=, __stack_pointer
; CHECK-NEXT: i32.load $push[[L13:.+]]=, 0($pop[[L1]])
; CHECK: i32.const $push[[L8:.+]]=, 0{{$}}
; CHECK-NEXT: i32.load $push[[L13:.+]]=, __stack_pointer($pop[[L1]])
; CHECK-NEXT: tee_local $push[[L12:.+]]=, [[SP:.+]], $pop[[L13]]{{$}}
; CHECK-NEXT: copy_local [[FP:.+]]=, $pop[[L12]]{{$}}
; Target independent codegen bumps the stack pointer
Expand All @@ -169,18 +170,18 @@ 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[[L7:.+]]=, __stack_pointer
; CHECK: i32.const $push[[L8:.+]]=, __stack_pointer
; CHECK: i32.const $push[[L9:.+]]=, __stack_pointer
; CHECK-NEXT: i32.load $push[[L10:.+]]=, 0($pop[[L9]])
; CHECK: i32.const $push[[L7:.+]]=, 0{{$}}
; CHECK: i32.const $push[[L8:.+]]=, 0{{$}}
; CHECK: i32.const $push[[L9:.+]]=, 0{{$}}
; CHECK-NEXT: i32.load $push[[L10:.+]]=, __stack_pointer($pop[[L9]])
; CHECK-NEXT: i32.const $push[[L11:.+]]=, 16
; CHECK-NEXT: i32.sub $push[[L20:.+]]=, $pop[[L10]], $pop[[L11]]
; CHECK-NEXT: tee_local $push[[L19:.+]]=, $[[FP:.+]]=, $pop[[L20]]
; CHECK: i32.store $push[[L0:.+]]=, 0($pop{{.+}}), $pop{{.+}}
; CHECK: i32.store $push[[L0:.+]]=, __stack_pointer($pop{{.+}}), $pop{{.+}}
; Decrement SP in the body by the dynamic amount.
; CHECK: i32.sub
; Writeback to memory.
; CHECK: i32.store $drop=, 0($pop{{.+}}), $pop{{.+}}
; CHECK: i32.store $drop=, __stack_pointer($pop{{.+}}), $pop{{.+}}
%r1 = alloca i32
%r = alloca i32, i32 %alloc
store i32 0, i32* %r
Expand Down Expand Up @@ -214,13 +215,13 @@ declare i8* @llvm.frameaddress(i32)

; Test __builtin_frame_address(0).
; CHECK-LABEL: frameaddress_0:
; CHECK: i32.const $push[[L0:.+]]=, __stack_pointer
; CHECK-NEXT: i32.load $push[[L3:.+]]=, 0($pop[[L0]])
; CHECK: i32.const $push[[L0:.+]]=, 0{{$}}
; CHECK-NEXT: i32.load $push[[L3:.+]]=, __stack_pointer($pop[[L0]])
; CHECK-NEXT: copy_local $push[[L4:.+]]=, $pop[[L3]]{{$}}
; CHECK-NEXT: tee_local $push[[L2:.+]]=, $[[FP:.+]]=, $pop[[L4]]{{$}}
; CHECK-NEXT: call use_i8_star@FUNCTION, $pop[[L2]]
; CHECK-NEXT: i32.const $push[[L1:.+]]=, __stack_pointer
; CHECK-NEXT: i32.store $drop=, 0($pop[[L1]]), $[[FP]]
; CHECK-NEXT: i32.const $push[[L1:.+]]=, 0{{$}}
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L1]]), $[[FP]]
define void @frameaddress_0() {
%t = call i8* @llvm.frameaddress(i32 0)
call void @use_i8_star(i8* %t)
Expand Down

0 comments on commit 04c5ee8

Please sign in to comment.