diff options
author | Derek Schuff <dschuff@google.com> | 2016-02-20 21:46:50 +0000 |
---|---|---|
committer | Derek Schuff <dschuff@google.com> | 2016-02-20 21:46:50 +0000 |
commit | dc5f6aa4bb3dccbee230a10d3cf26294c5093dfe (patch) | |
tree | c59f0c24283a0bf212e3a7b8f83b5bb70353dba0 /llvm/test/CodeGen/WebAssembly/userstack.ll | |
parent | d4768fa314c4bcd89a77d1134c7aaaddf12343dc (diff) | |
download | llvm-dc5f6aa4bb3dccbee230a10d3cf26294c5093dfe.zip llvm-dc5f6aa4bb3dccbee230a10d3cf26294c5093dfe.tar.gz llvm-dc5f6aa4bb3dccbee230a10d3cf26294c5093dfe.tar.bz2 |
[WebAssembly] Stackify function prologs and epilogs
The instructions are the same, but fewer locals are used.
Differential Revision: http://reviews.llvm.org/D17428
llvm-svn: 261452
Diffstat (limited to 'llvm/test/CodeGen/WebAssembly/userstack.ll')
-rw-r--r-- | llvm/test/CodeGen/WebAssembly/userstack.ll | 138 |
1 files changed, 70 insertions, 68 deletions
diff --git a/llvm/test/CodeGen/WebAssembly/userstack.ll b/llvm/test/CodeGen/WebAssembly/userstack.ll index 2032507..ac41c94 100644 --- a/llvm/test/CodeGen/WebAssembly/userstack.ll +++ b/llvm/test/CodeGen/WebAssembly/userstack.ll @@ -7,54 +7,58 @@ target triple = "wasm32-unknown-unknown" ; CHECK-LABEL: alloca32: ; Check that there is an extra local for the stack pointer. -; CHECK: .local i32, i32, i32, i32{{$}} +; CHECK: .local i32{{$}} define void @alloca32() { - ; CHECK: i32.const [[L1:.+]]=, __stack_pointer - ; CHECK-NEXT: i32.load [[L1]]=, 0([[L1]]) - ; CHECK-NEXT: i32.const [[L2:.+]]=, 16 - ; CHECK-NEXT: i32.sub [[SP:.+]]=, [[L1]], [[L2]] + ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer{{$}} + ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]]) + ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16 + ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]] + ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer{{$}} + ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L4]]), [[SP]] %retval = alloca i32 - ; CHECK: i32.const $push[[L3:.+]]=, 0 - ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]] + ; CHECK: i32.const $push[[L0:.+]]=, 0 + ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L0]] store i32 0, i32* %retval - ; CHECK: i32.const [[L4:.+]]=, 16 - ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], [[L4]] - ; CHECK-NEXT: i32.const [[L5:.+]]=, __stack_pointer - ; CHECK-NEXT: i32.store [[SP]]=, 0([[L5]]), [[SP]] + ; CHECK: i32.const $push[[L5:.+]]=, 16 + ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], $pop[[L5]] + ; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L6]]), [[SP]] ret void } ; CHECK-LABEL: alloca3264: -; CHECK: .local i32, i32, i32, i32{{$}} +; CHECK: .local i32{{$}} define void @alloca3264() { - ; CHECK: i32.const [[L1:.+]]=, __stack_pointer - ; CHECK-NEXT: i32.load [[L1]]=, 0([[L1]]) - ; CHECK-NEXT: i32.const [[L2:.+]]=, 16 - ; CHECK-NEXT: i32.sub [[SP:.+]]=, [[L1]], [[L2]] + ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]]) + ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16 + ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]] + ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer{{$}} + ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L4]]), [[SP]] %r1 = alloca i32 %r2 = alloca double ; CHECK: i32.const $push[[L3:.+]]=, 0 ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]] store i32 0, i32* %r1 - ; CHECK: i64.const $push[[L4:.+]]=, 0 - ; CHECK: i64.store {{.*}}=, 0([[SP]]), $pop[[L4]] + ; CHECK: i64.const $push[[L0:.+]]=, 0 + ; CHECK: i64.store {{.*}}=, 0([[SP]]), $pop[[L0]] store double 0.0, double* %r2 - ; CHECK: i32.const [[L4:.+]]=, 16 - ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], [[L4]] - ; CHECK-NEXT: i32.const [[L5:.+]]=, __stack_pointer - ; CHECK-NEXT: i32.store [[SP]]=, 0([[L5]]), [[SP]] + ; CHECK: i32.const $push[[L5:.+]]=, 16 + ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], $pop[[L5]] + ; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L6]]), [[SP]] ret void } ; CHECK-LABEL: allocarray: -; CHECK: .local i32, i32, i32, i32, i32{{$}} +; CHECK: .local i32, i32{{$}} define void @allocarray() { - ; CHECK-NEXT: 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]] - ; CHECK-NEXT: i32.const [[L2]]=, __stack_pointer{{$}} - ; CHECK-NEXT: i32.store [[SP]]=, 0([[L2]]), [[SP]] + ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]]) + ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 32{{$}} + ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]] + ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer{{$}} + ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L4]]), [[SP]] %r = alloca [5 x i32] ; CHECK-NEXT: i32.const $push[[L4:.+]]=, 12 @@ -69,18 +73,18 @@ define void @allocarray() { %p2 = getelementptr [5 x i32], [5 x i32]* %r, i32 0, i32 3 store i32 1, i32* %p2 - ; CHECK-NEXT: i32.const [[L7:.+]]=, 32 - ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], [[L7]] - ; CHECK-NEXT: i32.const [[L8:.+]]=, __stack_pointer - ; CHECK-NEXT: i32.store [[SP]]=, 0([[L8]]), [[SP]] + ; CHECK: i32.const $push[[L11:.+]]=, 32 + ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], $pop[[L11]] + ; CHECK-NEXT: i32.const $push[[L12:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L12]]), [[SP]] ret void } declare void @ext_func(i64* %ptr) ; CHECK-LABEL: non_mem_use define void @non_mem_use(i8** %addr) { - ; CHECK: i32.const [[L2:.+]]=, 48 - ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, [[L2]] + ; CHECK: i32.const $push[[L1:.+]]=, 48 + ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, $pop[[L1]] %buf = alloca [27 x i8], align 16 %r = alloca i64 %r2 = alloca i64 @@ -103,12 +107,12 @@ define void @non_mem_use(i8** %addr) { } ; CHECK-LABEL: allocarray_inbounds: -; CHECK: .local i32, i32, i32, i32{{$}} +; CHECK: .local i32{{$}} 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]] + ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]]) + ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 32{{$}} + ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]] %r = alloca [5 x i32] ; CHECK: i32.const $push[[L3:.+]]=, 1 ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]] @@ -118,45 +122,45 @@ define void @allocarray_inbounds() { ; CHECK-NEXT: i32.store {{.*}}=, 24([[SP]]), $pop %p2 = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 3 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]] + ; CHECK: i32.const $push[[L5:.+]]=, 32 + ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], $pop[[L5]] + ; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L6]]), [[SP]] ret void } ; CHECK-LABEL: dynamic_alloca: define void @dynamic_alloca(i32 %alloc) { - ; CHECK: i32.const [[L0:.+]]=, __stack_pointer - ; CHECK-NEXT: i32.load [[SP:.+]]=, 0([[L0]]) + ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.load [[SP:.+]]=, 0($pop[[L1]]) ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]] ; Target independent codegen bumps the stack pointer ; FIXME: we need to write the value back to memory %r = alloca i32, i32 %alloc ; Target-independent codegen also calculates the store addr store i32 0, i32* %r - ; CHECK: i32.const [[L3:.+]]=, __stack_pointer - ; CHECK-NEXT: i32.store [[SP]]=, 0([[L3]]), [[FP]] + ; CHECK: i32.const $push[[L3:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L3]]), [[FP]] ret void } ; CHECK-LABEL: dynamic_static_alloca: define void @dynamic_static_alloca(i32 %alloc) { - ; CHECK: i32.const [[L0:.+]]=, __stack_pointer - ; CHECK-NEXT: i32.load [[L0]]=, 0([[L0]]) - ; CHECK-NEXT: i32.const [[L2:.+]]=, 16 - ; CHECK-NEXT: i32.sub [[SP:.+]]=, [[L0]], [[L2]] + ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]]) + ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16 + ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]] ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]] - ; CHECK-NEXT: i32.const [[L3:.+]]=, __stack_pointer - ; CHECK-NEXT: i32.store {{.*}}=, 0([[L3]]), [[SP]] + ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.store {{.*}}=, 0($pop[[L4]]), [[SP]] %r1 = alloca i32 %r = alloca i32, i32 %alloc store i32 0, i32* %r - ; CHECK: i32.const [[L3:.+]]=, 16 - ; CHECK: i32.add [[SP]]=, [[FP]], [[L3]] - ; CHECK: i32.const [[L4:.+]]=, __stack_pointer - ; CHECK-NEXT: i32.store [[SP]]=, 0([[L4]]), [[SP]] + ; CHECK: i32.const $push[[L5:.+]]=, 16 + ; CHECK-NEXT: i32.add [[SP]]=, [[FP]], $pop[[L5]] + ; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer + ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L6]]), [[SP]] ret void } @@ -165,8 +169,8 @@ define void @dynamic_static_alloca(i32 %alloc) { ; CHECK-LABEL: copytoreg_fi: define void @copytoreg_fi(i1 %cond, i32* %b) { entry: - ; CHECK: i32.const [[L2:.+]]=, 16 - ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, [[L2]] + ; CHECK: i32.const $push[[L1:.+]]=, 16 + ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, $pop[[L1]] %addr = alloca i32 ; CHECK: i32.const [[OFF:.+]]=, 12 ; CHECK-NEXT: i32.add [[ADDR:.+]]=, [[SP]], [[OFF]] @@ -185,15 +189,13 @@ declare void @use_i8_star(i8*) declare i8* @llvm.frameaddress(i32) ; Test __builtin_frame_address(0). -; TODO: When the prolog/epilog sequences are optimized, refine these checks to -; be more specific. - ; CHECK-LABEL: frameaddress_0: -; CHECK: __stack_pointer -; CHECK: load -; CHECK: call use_i8_star -; CHECK: __stack_pointer -; CHECK: store +; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer +; CHECK-NEXT: i32.load [[SP:.+]]=, 0($pop[[L1]]) +; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]] +; CHECK-NEXT: call use_i8_star@FUNCTION, [[FP]] +; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer +; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L6]]), [[FP]] define void @frameaddress_0() { %t = call i8* @llvm.frameaddress(i32 0) call void @use_i8_star(i8* %t) |