1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 2; RUN: llc -mtriple=x86_64-apple-darwin10.6 < %s | FileCheck %s 3; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s --check-prefix=NOCOMPACTUNWIND 4; 5; Note: This test cannot be merged with the shrink-wrapping tests 6; because the booleans set on the command line take precedence on 7; the target logic that disable shrink-wrapping. 8 9; The current compact unwind scheme does not work when the prologue is not at 10; the start (the instructions before the prologue cannot be described). 11; Currently we choose to not perform shrink-wrapping for functions without FP 12; not marked as nounwind. PR25614 13; 14; No shrink-wrapping should occur here, until the CFI information are fixed. 15 16define i32 @framelessUnwind(i32 %a, i32 %b) #0 { 17; CHECK-LABEL: framelessUnwind: 18; CHECK: ## %bb.0: 19; CHECK-NEXT: pushq %rax 20; CHECK-NEXT: .cfi_def_cfa_offset 16 21; CHECK-NEXT: movl %edi, %eax 22; CHECK-NEXT: cmpl %esi, %edi 23; CHECK-NEXT: jge LBB0_2 24; CHECK-NEXT: ## %bb.1: ## %true 25; CHECK-NEXT: movl %eax, {{[0-9]+}}(%rsp) 26; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rsi 27; CHECK-NEXT: xorl %edi, %edi 28; CHECK-NEXT: callq _doSomething 29; CHECK-NEXT: LBB0_2: ## %false 30; CHECK-NEXT: popq %rcx 31; CHECK-NEXT: retq 32; 33; NOCOMPACTUNWIND-LABEL: framelessUnwind: 34; NOCOMPACTUNWIND: # %bb.0: 35; NOCOMPACTUNWIND-NEXT: movl %edi, %eax 36; NOCOMPACTUNWIND-NEXT: cmpl %esi, %edi 37; NOCOMPACTUNWIND-NEXT: jge .LBB0_2 38; NOCOMPACTUNWIND-NEXT: # %bb.1: # %true 39; NOCOMPACTUNWIND-NEXT: pushq %rax 40; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 41; NOCOMPACTUNWIND-NEXT: movl %eax, {{[0-9]+}}(%rsp) 42; NOCOMPACTUNWIND-NEXT: leaq {{[0-9]+}}(%rsp), %rsi 43; NOCOMPACTUNWIND-NEXT: xorl %edi, %edi 44; NOCOMPACTUNWIND-NEXT: callq doSomething@PLT 45; NOCOMPACTUNWIND-NEXT: addq $8, %rsp 46; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 47; NOCOMPACTUNWIND-NEXT: .LBB0_2: # %false 48; NOCOMPACTUNWIND-NEXT: retq 49 %tmp = alloca i32, align 4 50 %tmp2 = icmp slt i32 %a, %b 51 br i1 %tmp2, label %true, label %false 52 53true: 54 store i32 %a, ptr %tmp, align 4 55 %tmp4 = call i32 @doSomething(i32 0, ptr %tmp) 56 br label %false 57 58false: 59 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] 60 ret i32 %tmp.0 61} 62 63declare i32 @doSomething(i32, ptr) 64 65attributes #0 = { "frame-pointer"="none" } 66 67; Shrink-wrapping should occur here. We have a frame pointer. 68define i32 @frameUnwind(i32 %a, i32 %b) #1 { 69; CHECK-LABEL: frameUnwind: 70; CHECK: ## %bb.0: 71; CHECK-NEXT: movl %edi, %eax 72; CHECK-NEXT: cmpl %esi, %edi 73; CHECK-NEXT: jge LBB1_2 74; CHECK-NEXT: ## %bb.1: ## %true 75; CHECK-NEXT: pushq %rbp 76; CHECK-NEXT: .cfi_def_cfa_offset 16 77; CHECK-NEXT: .cfi_offset %rbp, -16 78; CHECK-NEXT: movq %rsp, %rbp 79; CHECK-NEXT: .cfi_def_cfa_register %rbp 80; CHECK-NEXT: subq $16, %rsp 81; CHECK-NEXT: movl %eax, -4(%rbp) 82; CHECK-NEXT: leaq -4(%rbp), %rsi 83; CHECK-NEXT: xorl %edi, %edi 84; CHECK-NEXT: callq _doSomething 85; CHECK-NEXT: addq $16, %rsp 86; CHECK-NEXT: popq %rbp 87; CHECK-NEXT: LBB1_2: ## %false 88; CHECK-NEXT: retq 89; 90; NOCOMPACTUNWIND-LABEL: frameUnwind: 91; NOCOMPACTUNWIND: # %bb.0: 92; NOCOMPACTUNWIND-NEXT: movl %edi, %eax 93; NOCOMPACTUNWIND-NEXT: cmpl %esi, %edi 94; NOCOMPACTUNWIND-NEXT: jge .LBB1_2 95; NOCOMPACTUNWIND-NEXT: # %bb.1: # %true 96; NOCOMPACTUNWIND-NEXT: pushq %rbp 97; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 98; NOCOMPACTUNWIND-NEXT: .cfi_offset %rbp, -16 99; NOCOMPACTUNWIND-NEXT: movq %rsp, %rbp 100; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_register %rbp 101; NOCOMPACTUNWIND-NEXT: subq $16, %rsp 102; NOCOMPACTUNWIND-NEXT: movl %eax, -4(%rbp) 103; NOCOMPACTUNWIND-NEXT: leaq -4(%rbp), %rsi 104; NOCOMPACTUNWIND-NEXT: xorl %edi, %edi 105; NOCOMPACTUNWIND-NEXT: callq doSomething@PLT 106; NOCOMPACTUNWIND-NEXT: addq $16, %rsp 107; NOCOMPACTUNWIND-NEXT: popq %rbp 108; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa %rsp, 8 109; NOCOMPACTUNWIND-NEXT: .cfi_restore %rbp 110; NOCOMPACTUNWIND-NEXT: .LBB1_2: # %false 111; NOCOMPACTUNWIND-NEXT: retq 112 %tmp = alloca i32, align 4 113 %tmp2 = icmp slt i32 %a, %b 114 br i1 %tmp2, label %true, label %false 115 116true: 117 store i32 %a, ptr %tmp, align 4 118 %tmp4 = call i32 @doSomething(i32 0, ptr %tmp) 119 br label %false 120 121false: 122 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] 123 ret i32 %tmp.0 124} 125 126attributes #1 = { "frame-pointer"="all" } 127 128; Shrink-wrapping should occur here. We do not have to unwind. 129define i32 @framelessnoUnwind(i32 %a, i32 %b) #2 { 130; CHECK-LABEL: framelessnoUnwind: 131; CHECK: ## %bb.0: 132; CHECK-NEXT: movl %edi, %eax 133; CHECK-NEXT: cmpl %esi, %edi 134; CHECK-NEXT: jge LBB2_2 135; CHECK-NEXT: ## %bb.1: ## %true 136; CHECK-NEXT: pushq %rax 137; CHECK-NEXT: movl %eax, {{[0-9]+}}(%rsp) 138; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rsi 139; CHECK-NEXT: xorl %edi, %edi 140; CHECK-NEXT: callq _doSomething 141; CHECK-NEXT: addq $8, %rsp 142; CHECK-NEXT: LBB2_2: ## %false 143; CHECK-NEXT: retq 144; 145; NOCOMPACTUNWIND-LABEL: framelessnoUnwind: 146; NOCOMPACTUNWIND: # %bb.0: 147; NOCOMPACTUNWIND-NEXT: movl %edi, %eax 148; NOCOMPACTUNWIND-NEXT: cmpl %esi, %edi 149; NOCOMPACTUNWIND-NEXT: jge .LBB2_2 150; NOCOMPACTUNWIND-NEXT: # %bb.1: # %true 151; NOCOMPACTUNWIND-NEXT: pushq %rax 152; NOCOMPACTUNWIND-NEXT: movl %eax, {{[0-9]+}}(%rsp) 153; NOCOMPACTUNWIND-NEXT: leaq {{[0-9]+}}(%rsp), %rsi 154; NOCOMPACTUNWIND-NEXT: xorl %edi, %edi 155; NOCOMPACTUNWIND-NEXT: callq doSomething@PLT 156; NOCOMPACTUNWIND-NEXT: addq $8, %rsp 157; NOCOMPACTUNWIND-NEXT: .LBB2_2: # %false 158; NOCOMPACTUNWIND-NEXT: retq 159 %tmp = alloca i32, align 4 160 %tmp2 = icmp slt i32 %a, %b 161 br i1 %tmp2, label %true, label %false 162 163true: 164 store i32 %a, ptr %tmp, align 4 165 %tmp4 = call i32 @doSomething(i32 0, ptr %tmp) 166 br label %false 167 168false: 169 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] 170 ret i32 %tmp.0 171} 172 173attributes #2 = { "frame-pointer"="none" nounwind } 174 175 176; Check that we generate correct code for segmented stack. 177; We used to emit the code at the entry point of the function 178; instead of just before the prologue. 179; For now, shrink-wrapping is disabled on segmented stack functions: PR26107. 180define zeroext i1 @segmentedStack(ptr readonly %vk1, ptr readonly %vk2, i64 %key_size) #5 { 181; CHECK-LABEL: segmentedStack: 182; CHECK: ## %bb.0: 183; CHECK-NEXT: cmpq %gs:816, %rsp 184; CHECK-NEXT: jbe LBB3_6 185; CHECK-NEXT: LBB3_1: ## %entry 186; CHECK-NEXT: pushq %rax 187; CHECK-NEXT: .cfi_def_cfa_offset 16 188; CHECK-NEXT: testq %rdi, %rdi 189; CHECK-NEXT: sete %al 190; CHECK-NEXT: testq %rsi, %rsi 191; CHECK-NEXT: sete %cl 192; CHECK-NEXT: orb %al, %cl 193; CHECK-NEXT: movq %rdi, %rax 194; CHECK-NEXT: orq %rsi, %rax 195; CHECK-NEXT: sete %al 196; CHECK-NEXT: testb %cl, %cl 197; CHECK-NEXT: jne LBB3_4 198; CHECK-NEXT: ## %bb.2: ## %if.end4.i 199; CHECK-NEXT: movq 8(%rdi), %rdx 200; CHECK-NEXT: cmpq 8(%rsi), %rdx 201; CHECK-NEXT: jne LBB3_5 202; CHECK-NEXT: ## %bb.3: ## %land.rhs.i.i 203; CHECK-NEXT: movq (%rsi), %rsi 204; CHECK-NEXT: movq (%rdi), %rdi 205; CHECK-NEXT: callq _memcmp 206; CHECK-NEXT: testl %eax, %eax 207; CHECK-NEXT: sete %al 208; CHECK-NEXT: LBB3_4: ## %__go_ptr_strings_equal.exit 209; CHECK-NEXT: ## kill: def $al killed $al killed $eax 210; CHECK-NEXT: popq %rcx 211; CHECK-NEXT: retq 212; CHECK-NEXT: LBB3_5: 213; CHECK-NEXT: xorl %eax, %eax 214; CHECK-NEXT: ## kill: def $al killed $al killed $eax 215; CHECK-NEXT: popq %rcx 216; CHECK-NEXT: retq 217; CHECK-NEXT: LBB3_6: 218; CHECK-NEXT: movl $8, %r10d 219; CHECK-NEXT: movl $0, %r11d 220; CHECK-NEXT: callq ___morestack 221; CHECK-NEXT: retq 222; CHECK-NEXT: jmp LBB3_1 223; 224; NOCOMPACTUNWIND-LABEL: segmentedStack: 225; NOCOMPACTUNWIND: # %bb.0: 226; NOCOMPACTUNWIND-NEXT: cmpq %fs:112, %rsp 227; NOCOMPACTUNWIND-NEXT: jbe .LBB3_6 228; NOCOMPACTUNWIND-NEXT: .LBB3_1: # %entry 229; NOCOMPACTUNWIND-NEXT: pushq %rax 230; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 231; NOCOMPACTUNWIND-NEXT: testq %rdi, %rdi 232; NOCOMPACTUNWIND-NEXT: sete %al 233; NOCOMPACTUNWIND-NEXT: testq %rsi, %rsi 234; NOCOMPACTUNWIND-NEXT: sete %cl 235; NOCOMPACTUNWIND-NEXT: orb %al, %cl 236; NOCOMPACTUNWIND-NEXT: movq %rdi, %rax 237; NOCOMPACTUNWIND-NEXT: orq %rsi, %rax 238; NOCOMPACTUNWIND-NEXT: sete %al 239; NOCOMPACTUNWIND-NEXT: testb %cl, %cl 240; NOCOMPACTUNWIND-NEXT: jne .LBB3_4 241; NOCOMPACTUNWIND-NEXT: # %bb.2: # %if.end4.i 242; NOCOMPACTUNWIND-NEXT: movq 8(%rdi), %rdx 243; NOCOMPACTUNWIND-NEXT: cmpq 8(%rsi), %rdx 244; NOCOMPACTUNWIND-NEXT: jne .LBB3_5 245; NOCOMPACTUNWIND-NEXT: # %bb.3: # %land.rhs.i.i 246; NOCOMPACTUNWIND-NEXT: movq (%rsi), %rsi 247; NOCOMPACTUNWIND-NEXT: movq (%rdi), %rdi 248; NOCOMPACTUNWIND-NEXT: callq memcmp@PLT 249; NOCOMPACTUNWIND-NEXT: testl %eax, %eax 250; NOCOMPACTUNWIND-NEXT: sete %al 251; NOCOMPACTUNWIND-NEXT: .LBB3_4: # %__go_ptr_strings_equal.exit 252; NOCOMPACTUNWIND-NEXT: # kill: def $al killed $al killed $eax 253; NOCOMPACTUNWIND-NEXT: popq %rcx 254; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 255; NOCOMPACTUNWIND-NEXT: retq 256; NOCOMPACTUNWIND-NEXT: .LBB3_5: 257; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 258; NOCOMPACTUNWIND-NEXT: xorl %eax, %eax 259; NOCOMPACTUNWIND-NEXT: # kill: def $al killed $al killed $eax 260; NOCOMPACTUNWIND-NEXT: popq %rcx 261; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 262; NOCOMPACTUNWIND-NEXT: retq 263; NOCOMPACTUNWIND-NEXT: .LBB3_6: 264; NOCOMPACTUNWIND-NEXT: movl $8, %r10d 265; NOCOMPACTUNWIND-NEXT: movl $0, %r11d 266; NOCOMPACTUNWIND-NEXT: callq __morestack 267; NOCOMPACTUNWIND-NEXT: retq 268; NOCOMPACTUNWIND-NEXT: jmp .LBB3_1 269entry: 270 %cmp.i = icmp eq ptr %vk1, null 271 %cmp1.i = icmp eq ptr %vk2, null 272 %brmerge.i = or i1 %cmp.i, %cmp1.i 273 %cmp1.mux.i = and i1 %cmp.i, %cmp1.i 274 br i1 %brmerge.i, label %__go_ptr_strings_equal.exit, label %if.end4.i 275 276if.end4.i: ; preds = %entry 277 %tmp = getelementptr inbounds i8, ptr %vk1, i64 8 278 %tmp2 = load i64, ptr %tmp, align 8 279 %tmp3 = getelementptr inbounds i8, ptr %vk2, i64 8 280 %tmp5 = load i64, ptr %tmp3, align 8 281 %cmp.i.i = icmp eq i64 %tmp2, %tmp5 282 br i1 %cmp.i.i, label %land.rhs.i.i, label %__go_ptr_strings_equal.exit 283 284land.rhs.i.i: ; preds = %if.end4.i 285 %tmp7 = load ptr, ptr %vk2, align 8 286 %tmp9 = load ptr, ptr %vk1, align 8 287 %call.i.i = tail call i32 @memcmp(ptr %tmp9, ptr %tmp7, i64 %tmp2) #5 288 %cmp4.i.i = icmp eq i32 %call.i.i, 0 289 br label %__go_ptr_strings_equal.exit 290 291__go_ptr_strings_equal.exit: ; preds = %land.rhs.i.i, %if.end4.i, %entry 292 %retval.0.i = phi i1 [ %cmp1.mux.i, %entry ], [ false, %if.end4.i ], [ %cmp4.i.i, %land.rhs.i.i ] 293 ret i1 %retval.0.i 294} 295 296; Function Attrs: nounwind readonly 297declare i32 @memcmp(ptr nocapture, ptr nocapture, i64) #5 298 299attributes #5 = { nounwind readonly ssp uwtable "split-stack" } 300 301; Check that correctly take into account the jumps to landing pad. 302; We used to consider function that may throw like regular 303; function calls. 304; Therefore, in this example, we were happily inserting the epilogue 305; right after the call to throw_exception. Because of that we would not 306; execute the epilogue when an execption occur and bad things will 307; happen. 308; PR36513 309define void @with_nounwind(i1 %cond) nounwind personality ptr @my_personality { 310; CHECK-LABEL: with_nounwind: 311; CHECK: ## %bb.0: ## %entry 312; CHECK-NEXT: pushq %rax 313; CHECK-NEXT: .cfi_def_cfa_offset 16 314; CHECK-NEXT: testb $1, %dil 315; CHECK-NEXT: jne LBB4_1 316; CHECK-NEXT: ## %bb.4: ## %return 317; CHECK-NEXT: popq %rax 318; CHECK-NEXT: retq 319; CHECK-NEXT: LBB4_1: ## %throw 320; CHECK-NEXT: Ltmp0: 321; CHECK-NEXT: callq _throw_exception 322; CHECK-NEXT: Ltmp1: 323; CHECK-NEXT: ## %bb.2: ## %unreachable 324; CHECK-NEXT: ud2 325; CHECK-NEXT: LBB4_3: ## %landing 326; CHECK-NEXT: Ltmp2: 327; CHECK-NEXT: popq %rax 328; CHECK-NEXT: retq 329; CHECK-NEXT: Lfunc_end0: 330; 331; NOCOMPACTUNWIND-LABEL: with_nounwind: 332; NOCOMPACTUNWIND: # %bb.0: # %entry 333; NOCOMPACTUNWIND-NEXT: pushq %rax 334; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 335; NOCOMPACTUNWIND-NEXT: testb $1, %dil 336; NOCOMPACTUNWIND-NEXT: jne .LBB4_1 337; NOCOMPACTUNWIND-NEXT: # %bb.4: # %return 338; NOCOMPACTUNWIND-NEXT: popq %rax 339; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 340; NOCOMPACTUNWIND-NEXT: retq 341; NOCOMPACTUNWIND-NEXT: .LBB4_1: # %throw 342; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 343; NOCOMPACTUNWIND-NEXT: .Ltmp0: 344; NOCOMPACTUNWIND-NEXT: callq throw_exception@PLT 345; NOCOMPACTUNWIND-NEXT: .Ltmp1: 346; NOCOMPACTUNWIND-NEXT: # %bb.2: # %unreachable 347; NOCOMPACTUNWIND-NEXT: .LBB4_3: # %landing 348; NOCOMPACTUNWIND-NEXT: .Ltmp2: 349; NOCOMPACTUNWIND-NEXT: popq %rax 350; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 351; NOCOMPACTUNWIND-NEXT: retq 352entry: 353 br i1 %cond, label %throw, label %return 354 355throw: 356 invoke void @throw_exception() 357 to label %unreachable unwind label %landing 358 359unreachable: 360 unreachable 361 362landing: 363 %pad = landingpad { ptr, i32 } 364 catch ptr null 365 ret void 366 367return: 368 ret void 369} 370 371; Check landing pad again. 372; This time checks that we can shrink-wrap when the epilogue does not 373; span accross several blocks. 374define void @with_nounwind_same_succ(i1 %cond) nounwind personality ptr @my_personality2 { 375; CHECK-LABEL: with_nounwind_same_succ: 376; CHECK: ## %bb.0: ## %entry 377; CHECK-NEXT: testb $1, %dil 378; CHECK-NEXT: je LBB5_4 379; CHECK-NEXT: ## %bb.1: ## %throw 380; CHECK-NEXT: pushq %rax 381; CHECK-NEXT: .cfi_def_cfa_offset 16 382; CHECK-NEXT: Ltmp3: 383; CHECK-NEXT: callq _throw_exception 384; CHECK-NEXT: Ltmp4: 385; CHECK-NEXT: LBB5_3: ## %fallthrough 386; CHECK-NEXT: ## InlineAsm Start 387; CHECK-NEXT: nop 388; CHECK-NEXT: ## InlineAsm End 389; CHECK-NEXT: popq %rax 390; CHECK-NEXT: LBB5_4: ## %return 391; CHECK-NEXT: retq 392; CHECK-NEXT: LBB5_2: ## %landing 393; CHECK-NEXT: Ltmp5: 394; CHECK-NEXT: jmp LBB5_3 395; CHECK-NEXT: Lfunc_end1: 396; 397; NOCOMPACTUNWIND-LABEL: with_nounwind_same_succ: 398; NOCOMPACTUNWIND: # %bb.0: # %entry 399; NOCOMPACTUNWIND-NEXT: testb $1, %dil 400; NOCOMPACTUNWIND-NEXT: je .LBB5_4 401; NOCOMPACTUNWIND-NEXT: # %bb.1: # %throw 402; NOCOMPACTUNWIND-NEXT: pushq %rax 403; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 404; NOCOMPACTUNWIND-NEXT: .Ltmp3: 405; NOCOMPACTUNWIND-NEXT: callq throw_exception@PLT 406; NOCOMPACTUNWIND-NEXT: .Ltmp4: 407; NOCOMPACTUNWIND-NEXT: .LBB5_3: # %fallthrough 408; NOCOMPACTUNWIND-NEXT: #APP 409; NOCOMPACTUNWIND-NEXT: nop 410; NOCOMPACTUNWIND-NEXT: #NO_APP 411; NOCOMPACTUNWIND-NEXT: popq %rax 412; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 8 413; NOCOMPACTUNWIND-NEXT: .LBB5_4: # %return 414; NOCOMPACTUNWIND-NEXT: retq 415; NOCOMPACTUNWIND-NEXT: .LBB5_2: # %landing 416; NOCOMPACTUNWIND-NEXT: .cfi_def_cfa_offset 16 417; NOCOMPACTUNWIND-NEXT: .Ltmp5: 418; NOCOMPACTUNWIND-NEXT: jmp .LBB5_3 419entry: 420 br i1 %cond, label %throw, label %return 421 422throw: 423 invoke void @throw_exception() 424 to label %fallthrough unwind label %landing 425landing: 426 %pad = landingpad { ptr, i32 } 427 catch ptr null 428 br label %fallthrough 429 430fallthrough: 431 tail call void asm "nop", ""() 432 br label %return 433 434return: 435 ret void 436} 437 438declare void @throw_exception() 439declare i32 @my_personality(...) 440declare i32 @my_personality2(...) 441