OLD | NEW |
(Empty) | |
| 1 ; RUN: opt %s -minsfi-expand-allocas -S | FileCheck %s |
| 2 |
| 3 !llvm.module.flags = !{!0} |
| 4 !0 = metadata !{i32 1, metadata !"Debug Info Version", i32 2} |
| 5 |
| 6 target datalayout = "p:32:32:32" |
| 7 target triple = "le32-unknown-nacl" |
| 8 |
| 9 ; Check that the stack pointer global variable is created. This does not check |
| 10 ; the initial value of the stack ptr. |
| 11 ; CHECK: @__sfi_stack_ptr = internal global i32 |
| 12 |
| 13 declare i8* @llvm.stacksave() |
| 14 declare void @llvm.stackrestore(i8* %ptr) |
| 15 |
| 16 declare void @foo() |
| 17 |
| 18 define i32 @test_no_alloca(i1 %cond) { |
| 19 br i1 %cond, label %IfOne, label %IfNotOne |
| 20 IfOne: |
| 21 call void @foo() |
| 22 ret i32 2 |
| 23 IfNotOne: |
| 24 ret i32 3 |
| 25 } |
| 26 |
| 27 ; CHECK-LABEL: define i32 @test_no_alloca(i1 %cond) { |
| 28 ; CHECK-NEXT: br i1 %cond, label %IfOne, label %IfNotOne |
| 29 ; CHECK: IfOne: |
| 30 ; CHECK-NEXT: call void @foo() |
| 31 ; CHECK-NEXT: ret i32 2 |
| 32 ; CHECK: IfNotOne: |
| 33 ; CHECK-NEXT: ret i32 3 |
| 34 ; CHECK-NEXT: } |
| 35 |
| 36 define i8* @test_const_alloca() { |
| 37 %ptr = alloca i8, i32 9, !dbg !1 |
| 38 ret i8* %ptr |
| 39 } |
| 40 |
| 41 ; CHECK-LABEL: define i8* @test_const_alloca() { |
| 42 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 43 ; CHECK-NEXT: %1 = sub i32 %frame_top, 9 |
| 44 ; CHECK-NEXT: %ptr = inttoptr i32 %1 to i8*, !dbg !1 |
| 45 ; CHECK-NEXT: ret i8* %ptr |
| 46 ; CHECK-NEXT: } |
| 47 |
| 48 define i8* @test_const_alloca_align() { |
| 49 %ptr = alloca i8, i32 9, align 536870912 ; biggest possible alignment |
| 50 ret i8* %ptr |
| 51 } |
| 52 |
| 53 ; CHECK-LABEL: define i8* @test_const_alloca_align() { |
| 54 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 55 ; CHECK-NEXT: %1 = sub i32 %frame_top, 9 |
| 56 ; CHECK-NEXT: %2 = and i32 %1, -536870912 |
| 57 ; CHECK-NEXT: %ptr = inttoptr i32 %2 to i8* |
| 58 ; CHECK-NEXT: ret i8* %ptr |
| 59 ; CHECK-NEXT: } |
| 60 |
| 61 define i8* @test_variable_length_alloca(i32 %size) { |
| 62 %ptr = alloca i8, i32 %size, !dbg !1 |
| 63 ret i8* %ptr |
| 64 } |
| 65 |
| 66 ; CHECK-LABEL: define i8* @test_variable_length_alloca(i32 %size) { |
| 67 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 68 ; CHECK-NEXT: %1 = sub i32 %frame_top, %size |
| 69 ; CHECK-NEXT: %ptr = inttoptr i32 %1 to i8*, !dbg !1 |
| 70 ; CHECK-NEXT: ret i8* %ptr |
| 71 ; CHECK-NEXT: } |
| 72 |
| 73 define i8* @test_variable_length_alloca_align(i32 %size) { |
| 74 %ptr = alloca i8, i32 %size, align 32 |
| 75 ret i8* %ptr |
| 76 } |
| 77 |
| 78 ; CHECK-LABEL: define i8* @test_variable_length_alloca_align(i32 %size) { |
| 79 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 80 ; CHECK-NEXT: %1 = sub i32 %frame_top, %size |
| 81 ; CHECK-NEXT: %2 = and i32 %1, -32 |
| 82 ; CHECK-NEXT: %ptr = inttoptr i32 %2 to i8* |
| 83 ; CHECK-NEXT: ret i8* %ptr |
| 84 ; CHECK-NEXT: } |
| 85 |
| 86 define i8* @test_const_after_const_alloca() { |
| 87 %ptr1 = alloca i8, i32 4 |
| 88 %ptr2 = alloca i8, i32 8 |
| 89 ret i8* %ptr2 |
| 90 } |
| 91 |
| 92 ; CHECK-LABEL: define i8* @test_const_after_const_alloca() { |
| 93 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 94 ; CHECK-NEXT: %1 = sub i32 %frame_top, 4 |
| 95 ; CHECK-NEXT: %ptr1 = inttoptr i32 %1 to i8* |
| 96 ; CHECK-NEXT: %2 = sub i32 %1, 8 |
| 97 ; CHECK-NEXT: %ptr2 = inttoptr i32 %2 to i8* |
| 98 ; CHECK-NEXT: ret i8* %ptr2 |
| 99 ; CHECK-NEXT: } |
| 100 |
| 101 define i8* @test_const_after_variable_alloca(i32 %size) { |
| 102 %ptr1 = alloca i8, i32 %size |
| 103 %ptr2 = alloca i8, i32 19 |
| 104 ret i8* %ptr2 |
| 105 } |
| 106 |
| 107 ; CHECK-LABEL: define i8* @test_const_after_variable_alloca(i32 %size) { |
| 108 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 109 ; CHECK-NEXT: %1 = sub i32 %frame_top, %size |
| 110 ; CHECK-NEXT: %ptr1 = inttoptr i32 %1 to i8* |
| 111 ; CHECK-NEXT: %2 = sub i32 %1, 19 |
| 112 ; CHECK-NEXT: %ptr2 = inttoptr i32 %2 to i8* |
| 113 ; CHECK-NEXT: ret i8* %ptr2 |
| 114 ; CHECK-NEXT: } |
| 115 |
| 116 define i8* @test_stacksave() { |
| 117 %ptr = call i8* @llvm.stacksave(), !dbg !1 |
| 118 ret i8* %ptr |
| 119 } |
| 120 |
| 121 ; CHECK-LABEL: define i8* @test_stacksave() { |
| 122 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 123 ; CHECK-NEXT: %ptr = inttoptr i32 %frame_top to i8*, !dbg !1 |
| 124 ; CHECK-NEXT: ret i8* %ptr |
| 125 ; CHECK-NEXT: } |
| 126 |
| 127 define i8* @test_stacksave_after_alloca() { |
| 128 %ptr1 = alloca i8, i32 11 |
| 129 %ptr2 = call i8* @llvm.stacksave(), !dbg !1 |
| 130 ret i8* %ptr2 |
| 131 } |
| 132 |
| 133 ; CHECK-LABEL: define i8* @test_stacksave_after_alloca() { |
| 134 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 135 ; CHECK-NEXT: %1 = sub i32 %frame_top, 11 |
| 136 ; CHECK-NEXT: %ptr1 = inttoptr i32 %1 to i8* |
| 137 ; CHECK-NEXT: %ptr2 = inttoptr i32 %1 to i8*, !dbg !1 |
| 138 ; CHECK-NEXT: ret i8* %ptr2 |
| 139 ; CHECK-NEXT: } |
| 140 |
| 141 define i8* @test_stackrestore(i8* %new_stack) { |
| 142 call void @llvm.stackrestore(i8* %new_stack), !dbg !1 |
| 143 %ptr = alloca i8, i32 5, !dbg !2 |
| 144 ret i8* %ptr |
| 145 } |
| 146 |
| 147 ; CHECK-LABEL: define i8* @test_stackrestore(i8* %new_stack) { |
| 148 ; CHECK-NEXT: frame_top = load i32* @__sfi_stack_ptr |
| 149 ; CHECK-NEXT: %1 = ptrtoint i8* %new_stack to i32, !dbg !1 |
| 150 ; CHECK-NEXT: %2 = sub i32 %1, 5 |
| 151 ; CHECK-NEXT: %ptr = inttoptr i32 %2 to i8*, !dbg !2 |
| 152 ; CHECK-NEXT: ret i8* %ptr |
| 153 ; CHECK-NEXT: } |
| 154 |
| 155 define i8* @test_stackrestore_after_push(i8* %new_stack) { |
| 156 %ptr1 = alloca i8, i32 5, !dbg !1 |
| 157 call void @llvm.stackrestore(i8* %new_stack), !dbg !2 |
| 158 %ptr2 = alloca i8, i32 6, !dbg !3 |
| 159 ret i8* %ptr2 |
| 160 } |
| 161 |
| 162 ; CHECK-LABEL: define i8* @test_stackrestore_after_push(i8* %new_stack) { |
| 163 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 164 ; CHECK-NEXT: %1 = sub i32 %frame_top, 5 |
| 165 ; CHECK-NEXT: %ptr1 = inttoptr i32 %1 to i8*, !dbg !1 |
| 166 ; CHECK-NEXT: %2 = ptrtoint i8* %new_stack to i32, !dbg !2 |
| 167 ; CHECK-NEXT: %3 = sub i32 %2, 6 |
| 168 ; CHECK-NEXT: %ptr2 = inttoptr i32 %3 to i8*, !dbg !3 |
| 169 ; CHECK-NEXT: ret i8* %ptr2 |
| 170 ; CHECK-NEXT: } |
| 171 |
| 172 define i8* @test_stackptr_bb_propagation(i1 %cond) { |
| 173 %ptr1 = alloca i8, i32 8 |
| 174 br i1 %cond, label %IfOne, label %IfNotOne |
| 175 IfOne: |
| 176 ret i8* %ptr1 |
| 177 IfNotOne: |
| 178 %ptr2 = alloca i8, i32 4 |
| 179 ret i8* %ptr2 |
| 180 } |
| 181 |
| 182 ; CHECK-LABEL: define i8* @test_stackptr_bb_propagation(i1 %cond) { |
| 183 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 184 ; CHECK-NEXT: %1 = sub i32 %frame_top, 8 |
| 185 ; CHECK-NEXT: %ptr1 = inttoptr i32 %1 to i8* |
| 186 ; CHECK-NEXT: br i1 %cond, label %IfOne, label %IfNotOne |
| 187 ; CHECK: IfOne: |
| 188 ; CHECK-NEXT: %2 = phi i32 [ %1, %0 ] |
| 189 ; CHECK-NEXT: ret i8* %ptr1 |
| 190 ; CHECK: IfNotOne: |
| 191 ; CHECK-NEXT: %3 = phi i32 [ %1, %0 ] |
| 192 ; CHECK-NEXT: %4 = sub i32 %3, 4 |
| 193 ; CHECK-NEXT: %ptr2 = inttoptr i32 %4 to i8* |
| 194 ; CHECK-NEXT: ret i8* %ptr2 |
| 195 ; CHECK-NEXT: } |
| 196 |
| 197 define i8* @test_scoped_alloca(i1 %cmp) { |
| 198 br label %loop |
| 199 loop: |
| 200 %stacksave = call i8* @llvm.stacksave() |
| 201 %ptr = alloca i8, i32 17 |
| 202 call void @llvm.stackrestore(i8* %stacksave) |
| 203 br i1 %cmp, label %done, label %loop |
| 204 done: |
| 205 ret i8* %ptr |
| 206 } |
| 207 |
| 208 ; CHECK-LABEL: define i8* @test_scoped_alloca(i1 %cmp) { |
| 209 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 210 ; CHECK-NEXT: br label %loop |
| 211 ; CHECK: loop: |
| 212 ; CHECK-NEXT: %1 = phi i32 [ %frame_top, %0 ], [ %3, %loop ] |
| 213 ; CHECK-NEXT: %stacksave = inttoptr i32 %1 to i8* |
| 214 ; CHECK-NEXT: %2 = sub i32 %1, 17 |
| 215 ; CHECK-NEXT: %ptr = inttoptr i32 %2 to i8* |
| 216 ; CHECK-NEXT: %3 = ptrtoint i8* %stacksave to i32 |
| 217 ; CHECK-NEXT: br i1 %cmp, label %done, label %loop |
| 218 ; CHECK: done: |
| 219 ; CHECK-NEXT: %4 = phi i32 [ %3, %loop ] |
| 220 ; CHECK-NEXT: ret i8* %ptr |
| 221 ; CHECK-NEXT: } |
| 222 |
| 223 define i8* @test_global_ptr_updates(i32 %size) { |
| 224 %ptr0 = call i8* @llvm.stacksave() |
| 225 %ptr1 = alloca i8, i32 32 |
| 226 %ptr2 = alloca i8, i32 %size |
| 227 call void @llvm.stackrestore(i8* %ptr0) |
| 228 call void @foo() |
| 229 ret i8* %ptr2 |
| 230 } |
| 231 |
| 232 ; CHECK-LABEL: define i8* @test_global_ptr_updates(i32 %size) { |
| 233 ; CHECK-NEXT: %frame_top = load i32* @__sfi_stack_ptr |
| 234 ; CHECK-NEXT: %ptr0 = inttoptr i32 %frame_top to i8* |
| 235 ; CHECK-NEXT: %1 = sub i32 %frame_top, 32 |
| 236 ; CHECK-NEXT: store i32 %1, i32* @__sfi_stack_ptr |
| 237 ; CHECK-NEXT: %ptr1 = inttoptr i32 %1 to i8* |
| 238 ; CHECK-NEXT: %2 = sub i32 %1, %size |
| 239 ; CHECK-NEXT: store i32 %2, i32* @__sfi_stack_ptr |
| 240 ; CHECK-NEXT: %ptr2 = inttoptr i32 %2 to i8* |
| 241 ; CHECK-NEXT: %3 = ptrtoint i8* %ptr0 to i32 |
| 242 ; CHECK-NEXT: store i32 %3, i32* @__sfi_stack_ptr |
| 243 ; CHECK-NEXT: call void @foo() |
| 244 ; CHECK-NEXT: store i32 %frame_top, i32* @__sfi_stack_ptr |
| 245 ; CHECK-NEXT: ret i8* %ptr2 |
| 246 ; CHECK-NEXT: } |
| 247 |
| 248 define i32 @_start_minsfi(i32 %args) { |
| 249 ret i32 0 |
| 250 } |
| 251 |
| 252 ; CHECK-LABEL: define i32 @_start_minsfi(i32 %args) { |
| 253 ; CHECK-NEXT: store i32 %args, i32* @__sfi_stack_ptr |
| 254 ; CHECK-NEXT: ret i32 0 |
| 255 ; CHECK-NEXT: } |
| 256 |
| 257 !1 = metadata !{i32 138, i32 0, metadata !1, null} |
| 258 !2 = metadata !{i32 142, i32 0, metadata !2, null} |
| 259 !3 = metadata !{i32 144, i32 0, metadata !3, null} |
OLD | NEW |