[WebAssembly] Put __stack_pointer in the offset field of loads and stores.

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

llvm-svn: 270635
This commit is contained in:
Dan Gohman 2016-05-24 23:47:41 +00:00
parent a9f38983e8
commit d530f68d45
4 changed files with 63 additions and 62 deletions

View File

@ -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);
@ -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);

View File

@ -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)
@ -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
}
@ -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){{$}}
@ -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]]{{$}}

View File

@ -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) {

View File

@ -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]]
@ -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
@ -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
}
@ -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]]
@ -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
@ -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
@ -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)