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