1 ; RUN: llc < %s | FileCheck %s 2 ; 3 ; Note: Print verbose stackmaps using -debug-only=stackmaps. 4 5 ; We are not getting the correct stack alignment when cross compiling for arm64. 6 ; So specify a datalayout here. 7 target datalayout = "E-m:e-i64:64-n32:64" 8 target triple = "powerpc64-unknown-linux-gnu" 9 10 ; CHECK-LABEL: constantargs: 11 ; CHECK: {{^}}.L[[constantargs_BEGIN:.*]]:{{$}} 12 13 ; CHECK-LABEL: osrinline: 14 ; CHECK: {{^}}.L[[osrinline_BEGIN:.*]]:{{$}} 15 16 ; CHECK-LABEL: osrcold: 17 ; CHECK: {{^}}.L[[osrcold_BEGIN:.*]]:{{$}} 18 19 ; CHECK-LABEL: propertyRead: 20 ; CHECK: {{^}}.L[[propertyRead_BEGIN:.*]]:{{$}} 21 22 ; CHECK-LABEL: propertyWrite: 23 ; CHECK: {{^}}.L[[propertyWrite_BEGIN:.*]]:{{$}} 24 25 ; CHECK-LABEL: jsVoidCall: 26 ; CHECK: {{^}}.L[[jsVoidCall_BEGIN:.*]]:{{$}} 27 28 ; CHECK-LABEL: jsIntCall: 29 ; CHECK: {{^}}.L[[jsIntCall_BEGIN:.*]]:{{$}} 30 31 ; CHECK-LABEL: spilledValue: 32 ; CHECK: {{^}}.L[[spilledValue_BEGIN:.*]]:{{$}} 33 34 ; CHECK-LABEL: spilledStackMapValue: 35 ; CHECK: {{^}}.L[[spilledStackMapValue_BEGIN:.*]]:{{$}} 36 37 ; CHECK-LABEL: liveConstant: 38 ; CHECK: {{^}}.L[[liveConstant_BEGIN:.*]]:{{$}} 39 40 ; CHECK-LABEL: clobberLR: 41 ; CHECK: {{^}}.L[[clobberLR_BEGIN:.*]]:{{$}} 42 43 44 ; CHECK-LABEL: .section .llvm_stackmaps 45 ; CHECK-NEXT: __LLVM_StackMaps: 46 ; Header 47 ; CHECK-NEXT: .byte 1 48 ; CHECK-NEXT: .byte 0 49 ; CHECK-NEXT: .short 0 50 ; Num Functions 51 ; CHECK-NEXT: .long 11 52 ; Num LargeConstants 53 ; CHECK-NEXT: .long 2 54 ; Num Callsites 55 ; CHECK-NEXT: .long 11 56 57 ; Functions and stack size 58 ; CHECK-NEXT: .quad constantargs 59 ; CHECK-NEXT: .quad 128 60 ; CHECK-NEXT: .quad osrinline 61 ; CHECK-NEXT: .quad 144 62 ; CHECK-NEXT: .quad osrcold 63 ; CHECK-NEXT: .quad 128 64 ; CHECK-NEXT: .quad propertyRead 65 ; CHECK-NEXT: .quad 128 66 ; CHECK-NEXT: .quad propertyWrite 67 ; CHECK-NEXT: .quad 128 68 ; CHECK-NEXT: .quad jsVoidCall 69 ; CHECK-NEXT: .quad 128 70 ; CHECK-NEXT: .quad jsIntCall 71 ; CHECK-NEXT: .quad 128 72 ; CHECK-NEXT: .quad spilledValue 73 ; CHECK-NEXT: .quad 304 74 ; CHECK-NEXT: .quad spilledStackMapValue 75 ; CHECK-NEXT: .quad 224 76 ; CHECK-NEXT: .quad liveConstant 77 ; CHECK-NEXT: .quad 64 78 ; CHECK-NEXT: .quad clobberLR 79 ; CHECK-NEXT: .quad 208 80 81 ; Num LargeConstants 82 ; CHECK-NEXT: .quad 4294967295 83 ; CHECK-NEXT: .quad 4294967296 84 85 ; Constant arguments 86 ; 87 ; CHECK-NEXT: .quad 1 88 ; CHECK-NEXT: .long .L{{.*}}-.L[[constantargs_BEGIN]] 89 ; CHECK-NEXT: .short 0 90 ; CHECK-NEXT: .short 4 91 ; SmallConstant 92 ; CHECK-NEXT: .byte 4 93 ; CHECK-NEXT: .byte 8 94 ; CHECK-NEXT: .short 0 95 ; CHECK-NEXT: .long 65535 96 ; SmallConstant 97 ; CHECK-NEXT: .byte 4 98 ; CHECK-NEXT: .byte 8 99 ; CHECK-NEXT: .short 0 100 ; CHECK-NEXT: .long 65536 101 ; SmallConstant 102 ; CHECK-NEXT: .byte 5 103 ; CHECK-NEXT: .byte 8 104 ; CHECK-NEXT: .short 0 105 ; CHECK-NEXT: .long 0 106 ; LargeConstant at index 0 107 ; CHECK-NEXT: .byte 5 108 ; CHECK-NEXT: .byte 8 109 ; CHECK-NEXT: .short 0 110 ; CHECK-NEXT: .long 1 111 112 define void @constantargs() { 113 entry: 114 %0 = inttoptr i64 244837814094590 to i8* 115 tail call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 1, i32 40, i8* %0, i32 0, i64 65535, i64 65536, i64 4294967295, i64 4294967296) 116 ret void 117 } 118 119 ; Inline OSR Exit 120 ; 121 ; CHECK: .long .L{{.*}}-.L[[osrinline_BEGIN]] 122 ; CHECK-NEXT: .short 0 123 ; CHECK-NEXT: .short 2 124 ; CHECK-NEXT: .byte 1 125 ; CHECK-NEXT: .byte 8 126 ; CHECK-NEXT: .short {{[0-9]+}} 127 ; CHECK-NEXT: .long 0 128 ; CHECK-NEXT: .byte 1 129 ; CHECK-NEXT: .byte 8 130 ; CHECK-NEXT: .short {{[0-9]+}} 131 ; CHECK-NEXT: .long 0 132 define void @osrinline(i64 %a, i64 %b) { 133 entry: 134 ; Runtime void->void call. 135 call void inttoptr (i64 244837814094590 to void ()*)() 136 ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars. 137 call void (i64, i32, ...) @llvm.experimental.stackmap(i64 3, i32 12, i64 %a, i64 %b) 138 ret void 139 } 140 141 ; Cold OSR Exit 142 ; 143 ; 2 live variables in register. 144 ; 145 ; CHECK: .long .L{{.*}}-.L[[osrcold_BEGIN]] 146 ; CHECK-NEXT: .short 0 147 ; CHECK-NEXT: .short 2 148 ; CHECK-NEXT: .byte 1 149 ; CHECK-NEXT: .byte 8 150 ; CHECK-NEXT: .short {{[0-9]+}} 151 ; CHECK-NEXT: .long 0 152 ; CHECK-NEXT: .byte 1 153 ; CHECK-NEXT: .byte 8 154 ; CHECK-NEXT: .short {{[0-9]+}} 155 ; CHECK-NEXT: .long 0 156 define void @osrcold(i64 %a, i64 %b) { 157 entry: 158 %test = icmp slt i64 %a, %b 159 br i1 %test, label %ret, label %cold 160 cold: 161 ; OSR patchpoint with 12-byte nop-slide and 2 live vars. 162 %thunk = inttoptr i64 244837814094590 to i8* 163 call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 4, i32 40, i8* %thunk, i32 0, i64 %a, i64 %b) 164 unreachable 165 ret: 166 ret void 167 } 168 169 ; Property Read 170 ; CHECK: .long .L{{.*}}-.L[[propertyRead_BEGIN]] 171 ; CHECK-NEXT: .short 0 172 ; CHECK-NEXT: .short 0 173 ; 174 ; FIXME: There are currently no stackmap entries. After moving to 175 ; AnyRegCC, we will have entries for the object and return value. 176 define i64 @propertyRead(i64* %obj) { 177 entry: 178 %resolveRead = inttoptr i64 244837814094590 to i8* 179 %result = call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 5, i32 40, i8* %resolveRead, i32 1, i64* %obj) 180 %add = add i64 %result, 3 181 ret i64 %add 182 } 183 184 ; Property Write 185 ; CHECK: .long .L{{.*}}-.L[[propertyWrite_BEGIN]] 186 ; CHECK-NEXT: .short 0 187 ; CHECK-NEXT: .short 2 188 ; CHECK-NEXT: .byte 1 189 ; CHECK-NEXT: .byte 8 190 ; CHECK-NEXT: .short {{[0-9]+}} 191 ; CHECK-NEXT: .long 0 192 ; CHECK-NEXT: .byte 1 193 ; CHECK-NEXT: .byte 8 194 ; CHECK-NEXT: .short {{[0-9]+}} 195 ; CHECK-NEXT: .long 0 196 define void @propertyWrite(i64 %dummy1, i64* %obj, i64 %dummy2, i64 %a) { 197 entry: 198 %resolveWrite = inttoptr i64 244837814094590 to i8* 199 call anyregcc void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 6, i32 40, i8* %resolveWrite, i32 2, i64* %obj, i64 %a) 200 ret void 201 } 202 203 ; Void JS Call 204 ; 205 ; 2 live variables in registers. 206 ; 207 ; CHECK: .long .L{{.*}}-.L[[jsVoidCall_BEGIN]] 208 ; CHECK-NEXT: .short 0 209 ; CHECK-NEXT: .short 2 210 ; CHECK-NEXT: .byte 1 211 ; CHECK-NEXT: .byte 8 212 ; CHECK-NEXT: .short {{[0-9]+}} 213 ; CHECK-NEXT: .long 0 214 ; CHECK-NEXT: .byte 1 215 ; CHECK-NEXT: .byte 8 216 ; CHECK-NEXT: .short {{[0-9]+}} 217 ; CHECK-NEXT: .long 0 218 define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 219 entry: 220 %resolveCall = inttoptr i64 244837814094590 to i8* 221 call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 7, i32 40, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2) 222 ret void 223 } 224 225 ; i64 JS Call 226 ; 227 ; 2 live variables in registers. 228 ; 229 ; CHECK: .long .L{{.*}}-.L[[jsIntCall_BEGIN]] 230 ; CHECK-NEXT: .short 0 231 ; CHECK-NEXT: .short 2 232 ; CHECK-NEXT: .byte 1 233 ; CHECK-NEXT: .byte 8 234 ; CHECK-NEXT: .short {{[0-9]+}} 235 ; CHECK-NEXT: .long 0 236 ; CHECK-NEXT: .byte 1 237 ; CHECK-NEXT: .byte 8 238 ; CHECK-NEXT: .short {{[0-9]+}} 239 ; CHECK-NEXT: .long 0 240 define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 241 entry: 242 %resolveCall = inttoptr i64 244837814094590 to i8* 243 %result = call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 8, i32 40, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2) 244 %add = add i64 %result, 3 245 ret i64 %add 246 } 247 248 ; Spilled stack map values. 249 ; 250 ; Verify 28 stack map entries. 251 ; 252 ; CHECK: .long .L{{.*}}-.L[[spilledValue_BEGIN]] 253 ; CHECK-NEXT: .short 0 254 ; CHECK-NEXT: .short 28 255 ; 256 ; Check that at least one is a spilled entry from r31. 257 ; Location: Indirect FP + ... 258 ; CHECK: .byte 3 259 ; CHECK-NEXT: .byte 8 260 ; CHECK-NEXT: .short 31 261 define void @spilledValue(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16, i64 %l17, i64 %l18, i64 %l19, i64 %l20, i64 %l21, i64 %l22, i64 %l23, i64 %l24, i64 %l25, i64 %l26, i64 %l27) { 262 entry: 263 call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 11, i32 40, i8* null, i32 5, i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16, i64 %l17, i64 %l18, i64 %l19, i64 %l20, i64 %l21, i64 %l22, i64 %l23, i64 %l24, i64 %l25, i64 %l26, i64 %l27) 264 ret void 265 } 266 267 ; Spilled stack map values. 268 ; 269 ; Verify 30 stack map entries. 270 ; 271 ; CHECK: .long .L{{.*}}-.L[[spilledStackMapValue_BEGIN]] 272 ; CHECK-NEXT: .short 0 273 ; CHECK-NEXT: .short 30 274 ; 275 ; Check that at least one is a spilled entry from r31. 276 ; Location: Indirect FP + ... 277 ; CHECK: .byte 3 278 ; CHECK-NEXT: .byte 8 279 ; CHECK-NEXT: .short 31 280 define webkit_jscc void @spilledStackMapValue(i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16, i64 %l17, i64 %l18, i64 %l19, i64 %l20, i64 %l21, i64 %l22, i64 %l23, i64 %l24, i64 %l25, i64 %l26, i64 %l27, i64 %l28, i64 %l29) { 281 entry: 282 call void (i64, i32, ...) @llvm.experimental.stackmap(i64 12, i32 16, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16, i64 %l17, i64 %l18, i64 %l19, i64 %l20, i64 %l21, i64 %l22, i64 %l23, i64 %l24, i64 %l25, i64 %l26, i64 %l27, i64 %l28, i64 %l29) 283 ret void 284 } 285 286 287 ; Map a constant value. 288 ; 289 ; CHECK: .long .L{{.*}}-.L[[liveConstant_BEGIN]] 290 ; CHECK-NEXT: .short 0 291 ; 1 location 292 ; CHECK-NEXT: .short 1 293 ; Loc 0: SmallConstant 294 ; CHECK-NEXT: .byte 4 295 ; CHECK-NEXT: .byte 8 296 ; CHECK-NEXT: .short 0 297 ; CHECK-NEXT: .long 33 298 299 define void @liveConstant() { 300 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 15, i32 8, i32 33) 301 ret void 302 } 303 304 ; Map a value when LR is the only free register. 305 ; 306 ; CHECK: .long .L{{.*}}-.L[[clobberLR_BEGIN]] 307 ; CHECK-NEXT: .short 0 308 ; 1 location 309 ; CHECK-NEXT: .short 1 310 ; Loc 0: Indirect FP (r31) - offset 311 ; CHECK-NEXT: .byte 3 312 ; CHECK-NEXT: .byte 4 313 ; CHECK-NEXT: .short 31 314 ; CHECK-NEXT: .long {{[0-9]+}} 315 define void @clobberLR(i32 %a) { 316 tail call void asm sideeffect "nop", "~{r0},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r14},~{r15},~{r16},~{r17},~{r18},~{r19},~{r20},~{r21},~{r22},~{r23},~{r24},~{r25},~{r26},~{r27},~{r28},~{r29},~{r30},~{r31}"() nounwind 317 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 16, i32 8, i32 %a) 318 ret void 319 } 320 321 declare void @llvm.experimental.stackmap(i64, i32, ...) 322 declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...) 323 declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...) 324