1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=i686-- -verify-machineinstrs < %s | FileCheck %s 3 4; A test for asm-goto output 5 6define i32 @test1(i32 %x) { 7; CHECK-LABEL: test1: 8; CHECK: # %bb.0: # %entry 9; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 10; CHECK-NEXT: addl $4, %eax 11; CHECK-NEXT: #APP 12; CHECK-NEXT: xorl %eax, %eax 13; CHECK-NEXT: jmp .LBB0_2 14; CHECK-NEXT: #NO_APP 15; CHECK-NEXT: # %bb.1: # %normal 16; CHECK-NEXT: retl 17; CHECK-NEXT: .LBB0_2: # Block address taken 18; CHECK-NEXT: # %abnormal 19; CHECK-NEXT: # Label of block must be emitted 20; CHECK-NEXT: movl $1, %eax 21; CHECK-NEXT: retl 22entry: 23 %add = add nsw i32 %x, 4 24 %ret = callbr i32 asm "xorl $1, $0; jmp ${2:l}", "=r,r,!i"(i32 %add) 25 to label %normal [label %abnormal] 26 27normal: 28 ret i32 %ret 29 30abnormal: 31 ret i32 1 32} 33 34define i32 @test2(i32 %out1, i32 %out2) nounwind { 35; CHECK-LABEL: test2: 36; CHECK: # %bb.0: # %entry 37; CHECK-NEXT: pushl %edi 38; CHECK-NEXT: pushl %esi 39; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edi 40; CHECK-NEXT: movl {{[0-9]+}}(%esp), %esi 41; CHECK-NEXT: cmpl %edi, %esi 42; CHECK-NEXT: jge .LBB1_3 43; CHECK-NEXT: # %bb.1: # %if.then 44; CHECK-NEXT: #APP 45; CHECK-NEXT: testl %esi, %esi 46; CHECK-NEXT: testl %edi, %esi 47; CHECK-NEXT: jne .LBB1_2 48; CHECK-NEXT: #NO_APP 49; CHECK-NEXT: jmp .LBB1_4 50; CHECK-NEXT: .LBB1_2: # Block address taken 51; CHECK-NEXT: # %if.then.label_true_crit_edge 52; CHECK-NEXT: # Label of block must be emitted 53; CHECK-NEXT: jmp .LBB1_9 54; CHECK-NEXT: .LBB1_3: # %if.else 55; CHECK-NEXT: #APP 56; CHECK-NEXT: testl %esi, %edi 57; CHECK-NEXT: testl %esi, %edi 58; CHECK-NEXT: jne .LBB1_7 59; CHECK-NEXT: #NO_APP 60; CHECK-NEXT: .LBB1_4: 61; CHECK-NEXT: movl %esi, %eax 62; CHECK-NEXT: addl %edi, %eax 63; CHECK-NEXT: .LBB1_5: # %return 64; CHECK-NEXT: popl %esi 65; CHECK-NEXT: popl %edi 66; CHECK-NEXT: retl 67; CHECK-NEXT: .LBB1_6: # Block address taken 68; CHECK-NEXT: # %if.then.return_crit_edge 69; CHECK-NEXT: # Label of block must be emitted 70; CHECK-NEXT: .LBB1_7: # Block address taken 71; CHECK-NEXT: # %if.else.return_crit_edge 72; CHECK-NEXT: # Label of block must be emitted 73; CHECK-NEXT: movl $-1, %eax 74; CHECK-NEXT: jmp .LBB1_5 75; CHECK-NEXT: .LBB1_8: # Block address taken 76; CHECK-NEXT: # %if.else.label_true_crit_edge 77; CHECK-NEXT: # Label of block must be emitted 78; CHECK-NEXT: .LBB1_9: # %label_true 79; CHECK-NEXT: movl $-2, %eax 80; CHECK-NEXT: jmp .LBB1_5 81entry: 82 %cmp = icmp slt i32 %out1, %out2 83 br i1 %cmp, label %if.then, label %if.else 84 85if.then: ; preds = %entry 86 %0 = callbr { i32, i32 } asm sideeffect "testl $0, $0; testl $1, $2; jne ${3:l}", "={si},={di},r,!i,!i,0,1"(i32 %out1, i32 %out1, i32 %out2) 87 to label %if.end [label %label_true, label %return] 88 89if.else: ; preds = %entry 90 %1 = callbr { i32, i32 } asm sideeffect "testl $0, $1; testl $2, $3; jne ${5:l}", "={si},={di},r,r,!i,!i,0,1"(i32 %out1, i32 %out2, i32 %out1, i32 %out2) 91 to label %if.end [label %label_true, label %return] 92 93if.end: ; preds = %if.else, %if.then 94 %.sink11 = phi { i32, i32 } [ %0, %if.then ], [ %1, %if.else ] 95 %asmresult3 = extractvalue { i32, i32 } %.sink11, 0 96 %asmresult4 = extractvalue { i32, i32 } %.sink11, 1 97 %add = add nsw i32 %asmresult4, %asmresult3 98 br label %return 99 100label_true: ; preds = %if.else, %if.then 101 br label %return 102 103return: ; preds = %if.then, %if.else, %label_true, %if.end 104 %retval.0 = phi i32 [ %add, %if.end ], [ -2, %label_true ], [ -1, %if.else ], [ -1, %if.then ] 105 ret i32 %retval.0 106} 107 108define i32 @test3(i1 %cmp) nounwind { 109; CHECK-LABEL: test3: 110; CHECK: # %bb.0: # %entry 111; CHECK-NEXT: pushl %edi 112; CHECK-NEXT: pushl %esi 113; CHECK-NEXT: testb $1, {{[0-9]+}}(%esp) 114; CHECK-NEXT: je .LBB2_3 115; CHECK-NEXT: # %bb.1: # %true 116; CHECK-NEXT: #APP 117; CHECK-NEXT: .short %esi 118; CHECK-NEXT: .short %edi 119; CHECK-NEXT: #NO_APP 120; CHECK-NEXT: # %bb.2: 121; CHECK-NEXT: movl %edi, %eax 122; CHECK-NEXT: jmp .LBB2_4 123; CHECK-NEXT: .LBB2_3: # %false 124; CHECK-NEXT: #APP 125; CHECK-NEXT: .short %eax 126; CHECK-NEXT: .short %edx 127; CHECK-NEXT: #NO_APP 128; CHECK-NEXT: movl %edx, %eax 129; CHECK-NEXT: .LBB2_4: # %asm.fallthrough 130; CHECK-NEXT: popl %esi 131; CHECK-NEXT: popl %edi 132; CHECK-NEXT: retl 133; CHECK-NEXT: .LBB2_5: # Block address taken 134; CHECK-NEXT: # %true.indirect_crit_edge 135; CHECK-NEXT: # Label of block must be emitted 136; CHECK-NEXT: .LBB2_6: # Block address taken 137; CHECK-NEXT: # %false.indirect_crit_edge 138; CHECK-NEXT: # Label of block must be emitted 139; CHECK-NEXT: movl $42, %eax 140; CHECK-NEXT: jmp .LBB2_4 141entry: 142 br i1 %cmp, label %true, label %false 143 144true: 145 %0 = callbr { i32, i32 } asm sideeffect ".word $0, $1", "={si},={di},!i" () to label %asm.fallthrough [label %indirect] 146 147false: 148 %1 = callbr { i32, i32 } asm sideeffect ".word $0, $1", "={ax},={dx},!i" () to label %asm.fallthrough [label %indirect] 149 150asm.fallthrough: 151 %vals = phi { i32, i32 } [ %0, %true ], [ %1, %false ] 152 %v = extractvalue { i32, i32 } %vals, 1 153 ret i32 %v 154 155indirect: 156 ret i32 42 157} 158 159; Test 4 - asm-goto with output constraints. 160define i32 @test4(i32 %out1, i32 %out2) { 161; CHECK-LABEL: test4: 162; CHECK: # %bb.0: # %entry 163; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 164; CHECK-NEXT: #APP 165; CHECK-NEXT: testl %eax, %eax 166; CHECK-NEXT: testl %ecx, %eax 167; CHECK-NEXT: jne .LBB3_5 168; CHECK-NEXT: #NO_APP 169; CHECK-NEXT: # %bb.1: # %asm.fallthrough 170; CHECK-NEXT: #APP 171; CHECK-NEXT: testl %eax, %ecx 172; CHECK-NEXT: testl %eax, %ecx 173; CHECK-NEXT: jne .LBB3_4 174; CHECK-NEXT: #NO_APP 175; CHECK-NEXT: # %bb.2: # %asm.fallthrough2 176; CHECK-NEXT: addl %ecx, %eax 177; CHECK-NEXT: retl 178; CHECK-NEXT: .LBB3_3: # Block address taken 179; CHECK-NEXT: # %entry.return_crit_edge 180; CHECK-NEXT: # Label of block must be emitted 181; CHECK-NEXT: .LBB3_4: # Block address taken 182; CHECK-NEXT: # %asm.fallthrough.return_crit_edge 183; CHECK-NEXT: # Label of block must be emitted 184; CHECK-NEXT: movl $-1, %eax 185; CHECK-NEXT: retl 186; CHECK-NEXT: .LBB3_5: # Block address taken 187; CHECK-NEXT: # %entry.label_true_crit_edge 188; CHECK-NEXT: # Label of block must be emitted 189; CHECK-NEXT: .LBB3_6: # Block address taken 190; CHECK-NEXT: # %asm.fallthrough.label_true_crit_edge 191; CHECK-NEXT: # Label of block must be emitted 192; CHECK-NEXT: movl $-2, %eax 193; CHECK-NEXT: retl 194entry: 195 %0 = callbr { i32, i32 } asm sideeffect "testl $0, $0; testl $1, $2; jne ${3:l}", "=r,=r,r,!i,!i"(i32 %out1) 196 to label %asm.fallthrough [label %label_true, label %return] 197 198asm.fallthrough: ; preds = %entry 199 %asmresult = extractvalue { i32, i32 } %0, 0 200 %asmresult1 = extractvalue { i32, i32 } %0, 1 201 %1 = callbr { i32, i32 } asm sideeffect "testl $0, $1; testl $2, $3; jne ${5:l}", "=r,=r,r,r,!i,!i"(i32 %asmresult, i32 %asmresult1) 202 to label %asm.fallthrough2 [label %label_true, label %return] 203 204asm.fallthrough2: ; preds = %asm.fallthrough 205 %asmresult3 = extractvalue { i32, i32 } %1, 0 206 %asmresult4 = extractvalue { i32, i32 } %1, 1 207 %add = add nsw i32 %asmresult3, %asmresult4 208 br label %return 209 210label_true: ; preds = %asm.fallthrough, %entry 211 br label %return 212 213return: ; preds = %entry, %asm.fallthrough, %label_true, %asm.fallthrough2 214 %retval.0 = phi i32 [ %add, %asm.fallthrough2 ], [ -2, %label_true ], [ -1, %asm.fallthrough ], [ -1, %entry ] 215 ret i32 %retval.0 216} 217 218; Test5 - test that we don't rely on a positional constraint. ie. +r in 219; GCCAsmStmt being turned into "={esp},0" since after D87279 they're turned 220; into "={esp},{esp}". This previously caused an ICE; this test is more so 221; about avoiding another ICE than what the actual output is. 222define dso_local void @test5() { 223; CHECK-LABEL: test5: 224; CHECK: # %bb.0: 225; CHECK-NEXT: #APP 226; CHECK-NEXT: #NO_APP 227; CHECK-NEXT: # %bb.1: 228; CHECK-NEXT: retl 229; CHECK-NEXT: .LBB4_2: # Block address taken 230; CHECK-NEXT: # %._crit_edge 231; CHECK-NEXT: # Label of block must be emitted 232; CHECK-NEXT: retl 233 %1 = call i32 @llvm.read_register.i32(metadata !3) 234 %2 = callbr i32 asm "", "={esp},!i,{esp}"(i32 %1) 235 to label %3 [label %4] 236 2373: 238 call void @llvm.write_register.i32(metadata !3, i32 %2) 239 br label %4 240 2414: 242 ret void 243} 244 245declare i32 @llvm.read_register.i32(metadata) 246declare void @llvm.write_register.i32(metadata, i32) 247!3 = !{!"esp"} 248