1; RUN: llc < %s -asm-verbose=false | FileCheck %s 2; RUN: llc < %s -asm-verbose=false -fast-isel | FileCheck %s 3 4 5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 6target triple = "wasm32-unknown-unknown" 7 8; CHECK-LABEL: alloca32: 9; Check that there is an extra local for the stack pointer. 10; CHECK: .local i32, i32, i32, i32{{$}} 11define void @alloca32() { 12 ; CHECK: i32.const [[L1:.+]]=, __stack_pointer 13 ; CHECK-NEXT: i32.load [[L1]]=, 0([[L1]]) 14 ; CHECK-NEXT: i32.const [[L2:.+]]=, 16 15 ; CHECK-NEXT: i32.sub [[SP:.+]]=, [[L1]], [[L2]] 16 %retval = alloca i32 17 ; CHECK: i32.const $push[[L3:.+]]=, 0 18 ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]] 19 store i32 0, i32* %retval 20 ; CHECK: i32.const [[L4:.+]]=, 16 21 ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], [[L4]] 22 ; CHECK-NEXT: i32.const [[L5:.+]]=, __stack_pointer 23 ; CHECK-NEXT: i32.store [[SP]]=, 0([[L5]]), [[SP]] 24 ret void 25} 26 27; CHECK-LABEL: alloca3264: 28; CHECK: .local i32, i32, i32, i32{{$}} 29define void @alloca3264() { 30 ; CHECK: i32.const [[L1:.+]]=, __stack_pointer 31 ; CHECK-NEXT: i32.load [[L1]]=, 0([[L1]]) 32 ; CHECK-NEXT: i32.const [[L2:.+]]=, 16 33 ; CHECK-NEXT: i32.sub [[SP:.+]]=, [[L1]], [[L2]] 34 %r1 = alloca i32 35 %r2 = alloca double 36 ; CHECK: i32.const $push[[L3:.+]]=, 0 37 ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]] 38 store i32 0, i32* %r1 39 ; CHECK: i64.const $push[[L4:.+]]=, 0 40 ; CHECK: i64.store {{.*}}=, 0([[SP]]), $pop[[L4]] 41 store double 0.0, double* %r2 42 ; CHECK: i32.const [[L4:.+]]=, 16 43 ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], [[L4]] 44 ; CHECK-NEXT: i32.const [[L5:.+]]=, __stack_pointer 45 ; CHECK-NEXT: i32.store [[SP]]=, 0([[L5]]), [[SP]] 46 ret void 47} 48 49; CHECK-LABEL: allocarray: 50; CHECK: .local i32, i32, i32, i32, i32{{$}} 51define void @allocarray() { 52 ; CHECK-NEXT: i32.const [[L1:.+]]=, __stack_pointer 53 ; CHECK-NEXT: i32.load [[L1]]=, 0([[L1]]) 54 ; CHECK-NEXT: i32.const [[L2:.+]]=, 32{{$}} 55 ; CHECK-NEXT: i32.sub [[SP:.+]]=, [[L1]], [[L2]] 56 ; CHECK-NEXT: i32.const [[L2]]=, __stack_pointer{{$}} 57 ; CHECK-NEXT: i32.store [[SP]]=, 0([[L2]]), [[SP]] 58 %r = alloca [5 x i32] 59 60 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, 12 61 ; CHECK-NEXT: i32.const [[L5:.+]]=, 12 62 ; CHECK-NEXT: i32.add [[L5]]=, [[SP]], [[L5]] 63 ; CHECK-NEXT: i32.add $push[[L6:.+]]=, [[L5]], $pop[[L4]] 64 ; CHECK-NEXT: i32.const $push[[L9:.+]]=, 1{{$}} 65 ; CHECK-NEXT: i32.store $push[[L10:.+]]=, 12([[SP]]), $pop[[L9]]{{$}} 66 ; CHECK-NEXT: i32.store $discard=, 0($pop3), $pop[[L10]]{{$}} 67 %p = getelementptr [5 x i32], [5 x i32]* %r, i32 0, i32 0 68 store i32 1, i32* %p 69 %p2 = getelementptr [5 x i32], [5 x i32]* %r, i32 0, i32 3 70 store i32 1, i32* %p2 71 72 ; CHECK-NEXT: i32.const [[L7:.+]]=, 32 73 ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], [[L7]] 74 ; CHECK-NEXT: i32.const [[L8:.+]]=, __stack_pointer 75 ; CHECK-NEXT: i32.store [[SP]]=, 0([[L8]]), [[SP]] 76 ret void 77} 78 79declare void @ext_func(i64* %ptr) 80; CHECK-LABEL: non_mem_use 81define void @non_mem_use() { 82 ; CHECK: i32.const [[L2:.+]]=, 16 83 ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, [[L2]] 84 %r = alloca i64 85 %r2 = alloca i64 86 ; %r is at SP+8 87 ; CHECK: i32.const [[OFF:.+]]=, 8 88 ; CHECK-NEXT: i32.add [[ARG1:.+]]=, [[SP]], [[OFF]] 89 ; CHECK-NEXT: call ext_func@FUNCTION, [[ARG1]] 90 call void @ext_func(i64* %r) 91 ; %r2 is at SP+0, no add needed 92 ; CHECK-NEXT: call ext_func@FUNCTION, [[SP]] 93 call void @ext_func(i64* %r2) 94 ret void 95} 96 97; CHECK-LABEL: allocarray_inbounds: 98; CHECK: .local i32, i32, i32, i32{{$}} 99define void @allocarray_inbounds() { 100 ; CHECK: i32.const [[L1:.+]]=, __stack_pointer 101 ; CHECK-NEXT: i32.load [[L1]]=, 0([[L1]]) 102 ; CHECK-NEXT: i32.const [[L2:.+]]=, 32 103 ; CHECK-NEXT: i32.sub [[SP:.+]]=, [[L1]], [[L2]] 104 %r = alloca [5 x i32] 105 ; CHECK: i32.const $push[[L3:.+]]=, 1 106 ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]] 107 %p = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 0 108 store i32 1, i32* %p 109 ; This store should have both the GEP and the FI folded into it. 110 ; CHECK-NEXT: i32.store {{.*}}=, 24([[SP]]), $pop 111 %p2 = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 3 112 store i32 1, i32* %p2 113 ; CHECK: i32.const [[L7:.+]]=, 32 114 ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], [[L7]] 115 ; CHECK-NEXT: i32.const [[L8:.+]]=, __stack_pointer 116 ; CHECK-NEXT: i32.store [[SP]]=, 0([[L7]]), [[SP]] 117 ret void 118} 119 120; CHECK-LABEL: dynamic_alloca: 121define void @dynamic_alloca(i32 %alloc) { 122 ; TODO: Support frame pointers 123 ;%r = alloca i32, i32 %alloc 124 ;store i32 0, i32* %r 125 ret void 126} 127; TODO: test aligned alloc 128