1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=i686-linux -show-mc-encoding | FileCheck %s --check-prefix=CHECK32 3; RUN: llc < %s -mtriple=x86_64-linux -show-mc-encoding | FileCheck %s --check-prefix=CHECK64 4; RUN: llc < %s -mtriple=x86_64-win32 -show-mc-encoding | FileCheck %s --check-prefix=WIN64 5 6declare void @foo() 7declare void @bar() 8 9define void @f(i32 %x, i32 %y) !prof !14 { 10; CHECK32-LABEL: f: 11; CHECK32: # %bb.0: # %entry 12; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x04] 13; CHECK32-NEXT: cmpl {{[0-9]+}}(%esp), %eax # encoding: [0x3b,0x44,0x24,0x08] 14; CHECK32-NEXT: jne bar@PLT # TAILCALL 15; CHECK32-NEXT: # encoding: [0x75,A] 16; CHECK32-NEXT: # fixup A - offset: 1, value: bar@PLT-1, kind: FK_PCRel_1 17; CHECK32-NEXT: # %bb.1: # %bb1 18; CHECK32-NEXT: jmp foo@PLT # TAILCALL 19; CHECK32-NEXT: # encoding: [0xeb,A] 20; CHECK32-NEXT: # fixup A - offset: 1, value: foo@PLT-1, kind: FK_PCRel_1 21; 22; CHECK64-LABEL: f: 23; CHECK64: # %bb.0: # %entry 24; CHECK64-NEXT: cmpl %esi, %edi # encoding: [0x39,0xf7] 25; CHECK64-NEXT: jne bar@PLT # TAILCALL 26; CHECK64-NEXT: # encoding: [0x75,A] 27; CHECK64-NEXT: # fixup A - offset: 1, value: bar@PLT-1, kind: FK_PCRel_1 28; CHECK64-NEXT: # %bb.1: # %bb1 29; CHECK64-NEXT: jmp foo@PLT # TAILCALL 30; CHECK64-NEXT: # encoding: [0xeb,A] 31; CHECK64-NEXT: # fixup A - offset: 1, value: foo@PLT-1, kind: FK_PCRel_1 32; 33; WIN64-LABEL: f: 34; WIN64: # %bb.0: # %entry 35; WIN64-NEXT: cmpl %edx, %ecx # encoding: [0x39,0xd1] 36; WIN64-NEXT: jne bar # TAILCALL 37; WIN64-NEXT: # encoding: [0x75,A] 38; WIN64-NEXT: # fixup A - offset: 1, value: bar-1, kind: FK_PCRel_1 39; WIN64-NEXT: # %bb.1: # %bb1 40; WIN64-NEXT: jmp foo # TAILCALL 41; WIN64-NEXT: # encoding: [0xeb,A] 42; WIN64-NEXT: # fixup A - offset: 1, value: foo-1, kind: FK_PCRel_1 43entry: 44 %p = icmp eq i32 %x, %y 45 br i1 %p, label %bb1, label %bb2 46bb1: 47 tail call void @foo() 48 ret void 49bb2: 50 tail call void @bar() 51 ret void 52 53; Check that the asm doesn't just look good, but uses the correct encoding. 54} 55 56define void @f_non_leaf(i32 %x, i32 %y) !prof !14 { 57; CHECK32-LABEL: f_non_leaf: 58; CHECK32: # %bb.0: # %entry 59; CHECK32-NEXT: pushl %ebx # encoding: [0x53] 60; CHECK32-NEXT: .cfi_def_cfa_offset 8 61; CHECK32-NEXT: .cfi_offset %ebx, -8 62; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %eax # encoding: [0x8b,0x44,0x24,0x08] 63; CHECK32-NEXT: #APP 64; CHECK32-NEXT: #NO_APP 65; CHECK32-NEXT: cmpl {{[0-9]+}}(%esp), %eax # encoding: [0x3b,0x44,0x24,0x0c] 66; CHECK32-NEXT: jne .LBB1_2 # encoding: [0x75,A] 67; CHECK32-NEXT: # fixup A - offset: 1, value: .LBB1_2-1, kind: FK_PCRel_1 68; CHECK32-NEXT: # %bb.1: # %bb1 69; CHECK32-NEXT: popl %ebx # encoding: [0x5b] 70; CHECK32-NEXT: .cfi_def_cfa_offset 4 71; CHECK32-NEXT: jmp foo@PLT # TAILCALL 72; CHECK32-NEXT: # encoding: [0xeb,A] 73; CHECK32-NEXT: # fixup A - offset: 1, value: foo@PLT-1, kind: FK_PCRel_1 74; CHECK32-NEXT: .LBB1_2: # %bb2 75; CHECK32-NEXT: .cfi_def_cfa_offset 8 76; CHECK32-NEXT: popl %ebx # encoding: [0x5b] 77; CHECK32-NEXT: .cfi_def_cfa_offset 4 78; CHECK32-NEXT: jmp bar@PLT # TAILCALL 79; CHECK32-NEXT: # encoding: [0xeb,A] 80; CHECK32-NEXT: # fixup A - offset: 1, value: bar@PLT-1, kind: FK_PCRel_1 81; 82; CHECK64-LABEL: f_non_leaf: 83; CHECK64: # %bb.0: # %entry 84; CHECK64-NEXT: pushq %rbx # encoding: [0x53] 85; CHECK64-NEXT: .cfi_def_cfa_offset 16 86; CHECK64-NEXT: .cfi_offset %rbx, -16 87; CHECK64-NEXT: #APP 88; CHECK64-NEXT: #NO_APP 89; CHECK64-NEXT: cmpl %esi, %edi # encoding: [0x39,0xf7] 90; CHECK64-NEXT: jne .LBB1_2 # encoding: [0x75,A] 91; CHECK64-NEXT: # fixup A - offset: 1, value: .LBB1_2-1, kind: FK_PCRel_1 92; CHECK64-NEXT: # %bb.1: # %bb1 93; CHECK64-NEXT: popq %rbx # encoding: [0x5b] 94; CHECK64-NEXT: .cfi_def_cfa_offset 8 95; CHECK64-NEXT: jmp foo@PLT # TAILCALL 96; CHECK64-NEXT: # encoding: [0xeb,A] 97; CHECK64-NEXT: # fixup A - offset: 1, value: foo@PLT-1, kind: FK_PCRel_1 98; CHECK64-NEXT: .LBB1_2: # %bb2 99; CHECK64-NEXT: .cfi_def_cfa_offset 16 100; CHECK64-NEXT: popq %rbx # encoding: [0x5b] 101; CHECK64-NEXT: .cfi_def_cfa_offset 8 102; CHECK64-NEXT: jmp bar@PLT # TAILCALL 103; CHECK64-NEXT: # encoding: [0xeb,A] 104; CHECK64-NEXT: # fixup A - offset: 1, value: bar@PLT-1, kind: FK_PCRel_1 105; 106; WIN64-LABEL: f_non_leaf: 107; WIN64: # %bb.0: # %entry 108; WIN64-NEXT: pushq %rbx # encoding: [0x53] 109; WIN64-NEXT: .seh_pushreg %rbx 110; WIN64-NEXT: .seh_endprologue 111; WIN64-NEXT: #APP 112; WIN64-NEXT: #NO_APP 113; WIN64-NEXT: cmpl %edx, %ecx # encoding: [0x39,0xd1] 114; WIN64-NEXT: jne .LBB1_2 # encoding: [0x75,A] 115; WIN64-NEXT: # fixup A - offset: 1, value: .LBB1_2-1, kind: FK_PCRel_1 116; WIN64-NEXT: # %bb.1: # %bb1 117; WIN64-NEXT: popq %rbx # encoding: [0x5b] 118; WIN64-NEXT: jmp foo # TAILCALL 119; WIN64-NEXT: # encoding: [0xeb,A] 120; WIN64-NEXT: # fixup A - offset: 1, value: foo-1, kind: FK_PCRel_1 121; WIN64-NEXT: .LBB1_2: # %bb2 122; WIN64-NEXT: nop # encoding: [0x90] 123; WIN64-NEXT: popq %rbx # encoding: [0x5b] 124; WIN64-NEXT: jmp bar # TAILCALL 125; WIN64-NEXT: # encoding: [0xeb,A] 126; WIN64-NEXT: # fixup A - offset: 1, value: bar-1, kind: FK_PCRel_1 127; WIN64-NEXT: .seh_endproc 128entry: 129 ; Force %ebx to be spilled on the stack, turning this into 130 ; not a "leaf" function for Win64. 131 tail call void asm sideeffect "", "~{ebx}"() 132 133 %p = icmp eq i32 %x, %y 134 br i1 %p, label %bb1, label %bb2 135bb1: 136 tail call void @foo() 137 ret void 138bb2: 139 tail call void @bar() 140 ret void 141 142} 143 144declare x86_thiscallcc zeroext i1 @baz(i8*, i32) 145define x86_thiscallcc zeroext i1 @BlockPlacementTest(i8* %this, i32 %x) !prof !14 { 146; CHECK32-LABEL: BlockPlacementTest: 147; CHECK32: # %bb.0: # %entry 148; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %edx # encoding: [0x8b,0x54,0x24,0x04] 149; CHECK32-NEXT: testb $42, %dl # encoding: [0xf6,0xc2,0x2a] 150; CHECK32-NEXT: je .LBB2_3 # encoding: [0x74,A] 151; CHECK32-NEXT: # fixup A - offset: 1, value: .LBB2_3-1, kind: FK_PCRel_1 152; CHECK32-NEXT: # %bb.1: # %land.rhs 153; CHECK32-NEXT: movb $1, %al # encoding: [0xb0,0x01] 154; CHECK32-NEXT: testb $44, %dl # encoding: [0xf6,0xc2,0x2c] 155; CHECK32-NEXT: je baz@PLT # TAILCALL 156; CHECK32-NEXT: # encoding: [0x74,A] 157; CHECK32-NEXT: # fixup A - offset: 1, value: baz@PLT-1, kind: FK_PCRel_1 158; CHECK32-NEXT: .LBB2_2: # %land.end 159; CHECK32-NEXT: # kill: def $al killed $al killed $eax 160; CHECK32-NEXT: retl $4 # encoding: [0xc2,0x04,0x00] 161; CHECK32-NEXT: .LBB2_3: 162; CHECK32-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] 163; CHECK32-NEXT: jmp .LBB2_2 # encoding: [0xeb,A] 164; CHECK32-NEXT: # fixup A - offset: 1, value: .LBB2_2-1, kind: FK_PCRel_1 165; 166; CHECK64-LABEL: BlockPlacementTest: 167; CHECK64: # %bb.0: # %entry 168; CHECK64-NEXT: testb $42, %sil # encoding: [0x40,0xf6,0xc6,0x2a] 169; CHECK64-NEXT: je .LBB2_3 # encoding: [0x74,A] 170; CHECK64-NEXT: # fixup A - offset: 1, value: .LBB2_3-1, kind: FK_PCRel_1 171; CHECK64-NEXT: # %bb.1: # %land.rhs 172; CHECK64-NEXT: movb $1, %al # encoding: [0xb0,0x01] 173; CHECK64-NEXT: testb $44, %sil # encoding: [0x40,0xf6,0xc6,0x2c] 174; CHECK64-NEXT: je baz@PLT # TAILCALL 175; CHECK64-NEXT: # encoding: [0x74,A] 176; CHECK64-NEXT: # fixup A - offset: 1, value: baz@PLT-1, kind: FK_PCRel_1 177; CHECK64-NEXT: .LBB2_2: # %land.end 178; CHECK64-NEXT: # kill: def $al killed $al killed $eax 179; CHECK64-NEXT: retq # encoding: [0xc3] 180; CHECK64-NEXT: .LBB2_3: 181; CHECK64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] 182; CHECK64-NEXT: jmp .LBB2_2 # encoding: [0xeb,A] 183; CHECK64-NEXT: # fixup A - offset: 1, value: .LBB2_2-1, kind: FK_PCRel_1 184; 185; WIN64-LABEL: BlockPlacementTest: 186; WIN64: # %bb.0: # %entry 187; WIN64-NEXT: testb $42, %dl # encoding: [0xf6,0xc2,0x2a] 188; WIN64-NEXT: je .LBB2_3 # encoding: [0x74,A] 189; WIN64-NEXT: # fixup A - offset: 1, value: .LBB2_3-1, kind: FK_PCRel_1 190; WIN64-NEXT: # %bb.1: # %land.rhs 191; WIN64-NEXT: movb $1, %al # encoding: [0xb0,0x01] 192; WIN64-NEXT: testb $44, %dl # encoding: [0xf6,0xc2,0x2c] 193; WIN64-NEXT: je baz # TAILCALL 194; WIN64-NEXT: # encoding: [0x74,A] 195; WIN64-NEXT: # fixup A - offset: 1, value: baz-1, kind: FK_PCRel_1 196; WIN64-NEXT: .LBB2_2: # %land.end 197; WIN64-NEXT: # kill: def $al killed $al killed $eax 198; WIN64-NEXT: retq # encoding: [0xc3] 199; WIN64-NEXT: .LBB2_3: 200; WIN64-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] 201; WIN64-NEXT: jmp .LBB2_2 # encoding: [0xeb,A] 202; WIN64-NEXT: # fixup A - offset: 1, value: .LBB2_2-1, kind: FK_PCRel_1 203entry: 204 %and = and i32 %x, 42 205 %tobool = icmp eq i32 %and, 0 206 br i1 %tobool, label %land.end, label %land.rhs 207 208land.rhs: 209 %and6 = and i32 %x, 44 210 %tobool7 = icmp eq i32 %and6, 0 211 br i1 %tobool7, label %lor.rhs, label %land.end 212 213lor.rhs: 214 %call = tail call x86_thiscallcc zeroext i1 @baz(i8* %this, i32 %x) #2 215 br label %land.end 216 217land.end: 218 %0 = phi i1 [ false, %entry ], [ true, %land.rhs ], [ %call, %lor.rhs ] 219 ret i1 %0 220 221; Make sure machine block placement isn't confused by the conditional tail call, 222; but sees that it can fall through to the next block. 223} 224 225!llvm.module.flags = !{!0} 226!0 = !{i32 1, !"ProfileSummary", !1} 227!1 = !{!2, !3, !4, !5, !6, !7, !8, !9} 228!2 = !{!"ProfileFormat", !"InstrProf"} 229!3 = !{!"TotalCount", i64 10000} 230!4 = !{!"MaxCount", i64 10} 231!5 = !{!"MaxInternalCount", i64 1} 232!6 = !{!"MaxFunctionCount", i64 1000} 233!7 = !{!"NumCounts", i64 3} 234!8 = !{!"NumFunctions", i64 3} 235!9 = !{!"DetailedSummary", !10} 236!10 = !{!11, !12, !13} 237!11 = !{i32 10000, i64 100, i32 1} 238!12 = !{i32 999000, i64 100, i32 1} 239!13 = !{i32 999999, i64 1, i32 2} 240!14 = !{!"function_entry_count", i64 0} 241