1; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 -disable-fp-elim | FileCheck %s 2; 3; Note: Print verbose stackmaps using -debug-only=stackmaps. 4 5; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps 6; CHECK-NEXT: __LLVM_StackMaps: 7; CHECK-NEXT: .long 0 8; Num LargeConstants 9; CHECK-NEXT: .long 1 10; CHECK-NEXT: .quad 4294967296 11; Num Callsites 12; CHECK-NEXT: .long 18 13 14; Constant arguments 15; 16; CHECK-NEXT: .quad 1 17; CHECK-NEXT: .long L{{.*}}-_constantargs 18; CHECK-NEXT: .short 0 19; CHECK-NEXT: .short 4 20; SmallConstant 21; CHECK-NEXT: .byte 4 22; CHECK-NEXT: .byte 8 23; CHECK-NEXT: .short 0 24; CHECK-NEXT: .long 65535 25; SmallConstant 26; CHECK-NEXT: .byte 4 27; CHECK-NEXT: .byte 8 28; CHECK-NEXT: .short 0 29; CHECK-NEXT: .long 65536 30; SmallConstant 31; CHECK-NEXT: .byte 4 32; CHECK-NEXT: .byte 8 33; CHECK-NEXT: .short 0 34; CHECK-NEXT: .long -1 35; LargeConstant at index 0 36; CHECK-NEXT: .byte 5 37; CHECK-NEXT: .byte 8 38; CHECK-NEXT: .short 0 39; CHECK-NEXT: .long 0 40 41define void @constantargs() { 42entry: 43 %0 = inttoptr i64 12345 to i8* 44 tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 1, i32 15, i8* %0, i32 0, i64 65535, i64 65536, i64 4294967295, i64 4294967296) 45 ret void 46} 47 48; Inline OSR Exit 49; 50; CHECK-LABEL: .long L{{.*}}-_osrinline 51; CHECK-NEXT: .short 0 52; CHECK-NEXT: .short 2 53; CHECK-NEXT: .byte 1 54; CHECK-NEXT: .byte 8 55; CHECK-NEXT: .short {{[0-9]+}} 56; CHECK-NEXT: .long 0 57; CHECK-NEXT: .byte 1 58; CHECK-NEXT: .byte 8 59; CHECK-NEXT: .short {{[0-9]+}} 60; CHECK-NEXT: .long 0 61define void @osrinline(i64 %a, i64 %b) { 62entry: 63 ; Runtime void->void call. 64 call void inttoptr (i64 -559038737 to void ()*)() 65 ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars. 66 call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 3, i32 12, i64 %a, i64 %b) 67 ret void 68} 69 70; Cold OSR Exit 71; 72; 2 live variables in register. 73; 74; CHECK-LABEL: .long L{{.*}}-_osrcold 75; CHECK-NEXT: .short 0 76; CHECK-NEXT: .short 2 77; CHECK-NEXT: .byte 1 78; CHECK-NEXT: .byte 8 79; CHECK-NEXT: .short {{[0-9]+}} 80; CHECK-NEXT: .long 0 81; CHECK-NEXT: .byte 1 82; CHECK-NEXT: .byte 8 83; CHECK-NEXT: .short {{[0-9]+}} 84; CHECK-NEXT: .long 0 85define void @osrcold(i64 %a, i64 %b) { 86entry: 87 %test = icmp slt i64 %a, %b 88 br i1 %test, label %ret, label %cold 89cold: 90 ; OSR patchpoint with 12-byte nop-slide and 2 live vars. 91 %thunk = inttoptr i64 -559038737 to i8* 92 call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4, i32 15, i8* %thunk, i32 0, i64 %a, i64 %b) 93 unreachable 94ret: 95 ret void 96} 97 98; Property Read 99; CHECK-LABEL: .long L{{.*}}-_propertyRead 100; CHECK-NEXT: .short 0 101; CHECK-NEXT: .short 2 102; CHECK-NEXT: .byte 1 103; CHECK-NEXT: .byte 8 104; CHECK-NEXT: .short {{[0-9]+}} 105; CHECK-NEXT: .long 0 106; CHECK-NEXT: .byte 1 107; CHECK-NEXT: .byte 8 108; CHECK-NEXT: .short {{[0-9]+}} 109; CHECK-NEXT: .long 0 110define i64 @propertyRead(i64* %obj) { 111entry: 112 %resolveRead = inttoptr i64 -559038737 to i8* 113 %result = call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 5, i32 15, i8* %resolveRead, i32 1, i64* %obj) 114 %add = add i64 %result, 3 115 ret i64 %add 116} 117 118; Property Write 119; CHECK-LABEL: .long L{{.*}}-_propertyWrite 120; CHECK-NEXT: .short 0 121; CHECK-NEXT: .short 2 122; CHECK-NEXT: .byte 1 123; CHECK-NEXT: .byte 8 124; CHECK-NEXT: .short {{[0-9]+}} 125; CHECK-NEXT: .long 0 126; CHECK-NEXT: .byte 1 127; CHECK-NEXT: .byte 8 128; CHECK-NEXT: .short {{[0-9]+}} 129; CHECK-NEXT: .long 0 130define void @propertyWrite(i64 %dummy1, i64* %obj, i64 %dummy2, i64 %a) { 131entry: 132 %resolveWrite = inttoptr i64 -559038737 to i8* 133 call anyregcc void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 6, i32 15, i8* %resolveWrite, i32 2, i64* %obj, i64 %a) 134 ret void 135} 136 137; Void JS Call 138; 139; 2 live variables in registers. 140; 141; CHECK-LABEL: .long L{{.*}}-_jsVoidCall 142; CHECK-NEXT: .short 0 143; CHECK-NEXT: .short 2 144; CHECK-NEXT: .byte 1 145; CHECK-NEXT: .byte 8 146; CHECK-NEXT: .short {{[0-9]+}} 147; CHECK-NEXT: .long 0 148; CHECK-NEXT: .byte 1 149; CHECK-NEXT: .byte 8 150; CHECK-NEXT: .short {{[0-9]+}} 151; CHECK-NEXT: .long 0 152define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 153entry: 154 %resolveCall = inttoptr i64 -559038737 to i8* 155 call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 7, i32 15, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2) 156 ret void 157} 158 159; i64 JS Call 160; 161; 2 live variables in registers. 162; 163; CHECK-LABEL: .long L{{.*}}-_jsIntCall 164; CHECK-NEXT: .short 0 165; CHECK-NEXT: .short 2 166; CHECK-NEXT: .byte 1 167; CHECK-NEXT: .byte 8 168; CHECK-NEXT: .short {{[0-9]+}} 169; CHECK-NEXT: .long 0 170; CHECK-NEXT: .byte 1 171; CHECK-NEXT: .byte 8 172; CHECK-NEXT: .short {{[0-9]+}} 173; CHECK-NEXT: .long 0 174define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) { 175entry: 176 %resolveCall = inttoptr i64 -559038737 to i8* 177 %result = call i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 8, i32 15, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2) 178 %add = add i64 %result, 3 179 ret i64 %add 180} 181 182; Spilled stack map values. 183; 184; Verify 17 stack map entries. 185; 186; CHECK-LABEL: .long L{{.*}}-_spilledValue 187; CHECK-NEXT: .short 0 188; CHECK-NEXT: .short 17 189; 190; Check that at least one is a spilled entry from RBP. 191; Location: Indirect RBP + ... 192; CHECK: .byte 3 193; CHECK-NEXT: .byte 8 194; CHECK-NEXT: .short 6 195define 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) { 196entry: 197 call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 11, i32 15, 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) 198 ret void 199} 200 201; Spilled stack map values. 202; 203; Verify 17 stack map entries. 204; 205; CHECK-LABEL: .long L{{.*}}-_spilledStackMapValue 206; CHECK-NEXT: .short 0 207; CHECK-NEXT: .short 17 208; 209; Check that at least one is a spilled entry from RBP. 210; Location: Indirect RBP + ... 211; CHECK: .byte 3 212; CHECK-NEXT: .byte 8 213; CHECK-NEXT: .short 6 214define 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) { 215entry: 216 call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 12, i32 15, 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) 217 ret void 218} 219 220; Spill a subregister stackmap operand. 221; 222; CHECK-LABEL: .long L{{.*}}-_spillSubReg 223; CHECK-NEXT: .short 0 224; 4 locations 225; CHECK-NEXT: .short 1 226; 227; Check that the subregister operand is a 4-byte spill. 228; Location: Indirect, 4-byte, RBP + ... 229; CHECK: .byte 3 230; CHECK-NEXT: .byte 4 231; CHECK-NEXT: .short 6 232define void @spillSubReg(i64 %arg) #0 { 233bb: 234 br i1 undef, label %bb1, label %bb2 235 236bb1: 237 unreachable 238 239bb2: 240 %tmp = load i64* inttoptr (i64 140685446136880 to i64*) 241 br i1 undef, label %bb16, label %bb17 242 243bb16: 244 unreachable 245 246bb17: 247 %tmp32 = trunc i64 %tmp to i32 248 br i1 undef, label %bb60, label %bb61 249 250bb60: 251 tail call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() nounwind 252 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 13, i32 5, i32 %tmp32) 253 unreachable 254 255bb61: 256 unreachable 257} 258 259; Map a single byte subregister. There is no DWARF register number, so 260; we expect the register to be encoded with the proper size and spill offset. We don't know which 261; 262; CHECK-LABEL: .long L{{.*}}-_subRegOffset 263; CHECK-NEXT: .short 0 264; 2 locations 265; CHECK-NEXT: .short 2 266; 267; Check that the subregister operands are 1-byte spills. 268; Location 0: Register, 4-byte, AL 269; CHECK-NEXT: .byte 1 270; CHECK-NEXT: .byte 1 271; CHECK-NEXT: .short 0 272; CHECK-NEXT: .long 0 273; 274; Location 1: Register, 4-byte, BL 275; CHECK-NEXT: .byte 1 276; CHECK-NEXT: .byte 1 277; CHECK-NEXT: .short 3 278; CHECK-NEXT: .long 0 279define void @subRegOffset(i16 %arg) { 280 %v = mul i16 %arg, 5 281 %a0 = trunc i16 %v to i8 282 tail call void asm sideeffect "nop", "~{bx}"() nounwind 283 %arghi = lshr i16 %v, 8 284 %a1 = trunc i16 %arghi to i8 285 tail call void asm sideeffect "nop", "~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() nounwind 286 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 14, i32 5, i8 %a0, i8 %a1) 287 ret void 288} 289 290; Map a constant value. 291; 292; CHECK-LABEL: .long L{{.*}}-_liveConstant 293; CHECK-NEXT: .short 0 294; 1 location 295; CHECK-NEXT: .short 1 296; Loc 0: SmallConstant 297; CHECK-NEXT: .byte 4 298; CHECK-NEXT: .byte 8 299; CHECK-NEXT: .short 0 300; CHECK-NEXT: .long 33 301 302define void @liveConstant() { 303 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 15, i32 5, i32 33) 304 ret void 305} 306 307; Directly map an alloca's address. 308; 309; Callsite 16 310; CHECK-LABEL: .long L{{.*}}-_directFrameIdx 311; CHECK-NEXT: .short 0 312; 1 location 313; CHECK-NEXT: .short 1 314; Loc 0: Direct RBP - ofs 315; CHECK-NEXT: .byte 2 316; CHECK-NEXT: .byte 8 317; CHECK-NEXT: .short 6 318; CHECK-NEXT: .long 319 320; Callsite 17 321; CHECK-LABEL: .long L{{.*}}-_directFrameIdx 322; CHECK-NEXT: .short 0 323; 2 locations 324; CHECK-NEXT: .short 2 325; Loc 0: Direct RBP - ofs 326; CHECK-NEXT: .byte 2 327; CHECK-NEXT: .byte 8 328; CHECK-NEXT: .short 6 329; CHECK-NEXT: .long 330; Loc 1: Direct RBP - ofs 331; CHECK-NEXT: .byte 2 332; CHECK-NEXT: .byte 8 333; CHECK-NEXT: .short 6 334; CHECK-NEXT: .long 335define void @directFrameIdx() { 336entry: 337 %metadata1 = alloca i64, i32 3, align 8 338 store i64 11, i64* %metadata1 339 store i64 12, i64* %metadata1 340 store i64 13, i64* %metadata1 341 call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 16, i32 0, i64* %metadata1) 342 %metadata2 = alloca i8, i32 4, align 8 343 %metadata3 = alloca i16, i32 4, align 8 344 call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 17, i32 5, i8* null, i32 0, i8* %metadata2, i16* %metadata3) 345 ret void 346} 347 348; Test a 64-bit ID. 349; 350; CHECK: .quad 4294967295 351; CHECK-LABEL: .long L{{.*}}-_longid 352; CHECK: .quad 4294967296 353; CHECK-LABEL: .long L{{.*}}-_longid 354; CHECK: .quad 9223372036854775807 355; CHECK-LABEL: .long L{{.*}}-_longid 356; CHECK: .quad -1 357; CHECK-LABEL: .long L{{.*}}-_longid 358define void @longid() { 359entry: 360 tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4294967295, i32 0, i8* null, i32 0) 361 tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4294967296, i32 0, i8* null, i32 0) 362 tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 9223372036854775807, i32 0, i8* null, i32 0) 363 tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 -1, i32 0, i8* null, i32 0) 364 ret void 365} 366 367declare void @llvm.experimental.stackmap(i64, i32, ...) 368declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...) 369declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...) 370