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(i8** %addr) { 82 ; CHECK: i32.const [[L2:.+]]=, 48 83 ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, [[L2]] 84 %buf = alloca [27 x i8], align 16 85 %r = alloca i64 86 %r2 = alloca i64 87 ; %r is at SP+8 88 ; CHECK: i32.const [[OFF:.+]]=, 8 89 ; CHECK-NEXT: i32.add [[ARG1:.+]]=, [[SP]], [[OFF]] 90 ; CHECK-NEXT: call ext_func@FUNCTION, [[ARG1]] 91 call void @ext_func(i64* %r) 92 ; %r2 is at SP+0, no add needed 93 ; CHECK-NEXT: call ext_func@FUNCTION, [[SP]] 94 call void @ext_func(i64* %r2) 95 ; Use as a value, but in a store 96 ; %buf is at SP+16 97 ; CHECK: i32.const [[OFF:.+]]=, 16 98 ; CHECK-NEXT: i32.add [[VAL:.+]]=, [[SP]], [[OFF]] 99 ; CHECK-NEXT: i32.store {{.*}}=, 0($0), [[VAL]] 100 %gep = getelementptr inbounds [27 x i8], [27 x i8]* %buf, i32 0, i32 0 101 store i8* %gep, i8** %addr 102 ret void 103} 104 105; CHECK-LABEL: allocarray_inbounds: 106; CHECK: .local i32, i32, i32, i32{{$}} 107define void @allocarray_inbounds() { 108 ; CHECK: i32.const [[L1:.+]]=, __stack_pointer 109 ; CHECK-NEXT: i32.load [[L1]]=, 0([[L1]]) 110 ; CHECK-NEXT: i32.const [[L2:.+]]=, 32 111 ; CHECK-NEXT: i32.sub [[SP:.+]]=, [[L1]], [[L2]] 112 %r = alloca [5 x i32] 113 ; CHECK: i32.const $push[[L3:.+]]=, 1 114 ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]] 115 %p = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 0 116 store i32 1, i32* %p 117 ; This store should have both the GEP and the FI folded into it. 118 ; CHECK-NEXT: i32.store {{.*}}=, 24([[SP]]), $pop 119 %p2 = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 3 120 store i32 1, i32* %p2 121 ; CHECK: i32.const [[L7:.+]]=, 32 122 ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], [[L7]] 123 ; CHECK-NEXT: i32.const [[L8:.+]]=, __stack_pointer 124 ; CHECK-NEXT: i32.store [[SP]]=, 0([[L7]]), [[SP]] 125 ret void 126} 127 128; CHECK-LABEL: dynamic_alloca: 129define void @dynamic_alloca(i32 %alloc) { 130 ; CHECK: i32.const [[L0:.+]]=, __stack_pointer 131 ; CHECK-NEXT: i32.load [[SP:.+]]=, 0([[L0]]) 132 ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]] 133 ; Target independent codegen bumps the stack pointer 134 ; FIXME: we need to write the value back to memory 135 %r = alloca i32, i32 %alloc 136 ; Target-independent codegen also calculates the store addr 137 store i32 0, i32* %r 138 ; CHECK: i32.const [[L3:.+]]=, __stack_pointer 139 ; CHECK-NEXT: i32.store [[SP]]=, 0([[L3]]), [[FP]] 140 ret void 141} 142 143 144; CHECK-LABEL: dynamic_static_alloca: 145define void @dynamic_static_alloca(i32 %alloc) { 146 ; CHECK: i32.const [[L0:.+]]=, __stack_pointer 147 ; CHECK-NEXT: i32.load [[L0]]=, 0([[L0]]) 148 ; CHECK-NEXT: i32.const [[L2:.+]]=, 16 149 ; CHECK-NEXT: i32.sub [[SP:.+]]=, [[L0]], [[L2]] 150 ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]] 151 ; CHECK-NEXT: i32.const [[L3:.+]]=, __stack_pointer 152 ; CHECK-NEXT: i32.store {{.*}}=, 0([[L3]]), [[SP]] 153 %r1 = alloca i32 154 %r = alloca i32, i32 %alloc 155 store i32 0, i32* %r 156 ; CHECK: i32.const [[L3:.+]]=, 16 157 ; CHECK: i32.add [[SP]]=, [[FP]], [[L3]] 158 ; CHECK: i32.const [[L4:.+]]=, __stack_pointer 159 ; CHECK-NEXT: i32.store [[SP]]=, 0([[L4]]), [[SP]] 160 ret void 161} 162 163; TODO: test over-aligned alloca 164