1 // REQUIRES: x86-registered-target 2 // RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s 3 // RUN: %clang_cc1 -no-opaque-pointers -triple i386-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s 4 5 int test1(int cond) { 6 // CHECK-LABEL: define{{.*}} i32 @test1( 7 // CHECK: callbr void asm sideeffect 8 // CHECK: to label %asm.fallthrough [label %label_true, label %loop] 9 // CHECK-LABEL: asm.fallthrough: 10 asm volatile goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop); 11 asm volatile goto("testl %0, %0; jne %l2;" :: "r"(cond)::label_true, loop); 12 // CHECK: callbr void asm sideeffect 13 // CHECK: to label %asm.fallthrough1 [label %label_true, label %loop] 14 // CHECK-LABEL: asm.fallthrough1: 15 return 0; 16 loop: 17 return 0; 18 label_true: 19 return 1; 20 } 21 22 int test2(int cond) { 23 // CHECK-LABEL: define{{.*}} i32 @test2( 24 // CHECK: callbr i32 asm sideeffect 25 // CHECK: to label %asm.fallthrough [label %label_true, label %loop] 26 // CHECK-LABEL: asm.fallthrough: 27 asm volatile goto("testl %0, %0; jne %l2;" : "=r"(cond) : "r"(cond) :: label_true, loop); 28 asm volatile goto("testl %0, %0; jne %l3;" : "=r"(cond) : "r"(cond) :: label_true, loop); 29 // CHECK: callbr i32 asm sideeffect 30 // CHECK: to label %asm.fallthrough1 [label %label_true, label %loop] 31 // CHECK-LABEL: asm.fallthrough1: 32 return 0; 33 loop: 34 return 0; 35 label_true: 36 return 1; 37 } 38 39 int test3(int out1, int out2) { 40 // CHECK-LABEL: define{{.*}} i32 @test3( 41 // CHECK: callbr { i32, i32 } asm sideeffect 42 // CHECK: to label %asm.fallthrough [label %label_true, label %loop] 43 // CHECK-LABEL: asm.fallthrough: 44 asm volatile goto("testl %0, %0; jne %l3;" : "=r"(out1), "=r"(out2) : "r"(out1) :: label_true, loop); 45 asm volatile goto("testl %0, %0; jne %l4;" : "=r"(out1), "=r"(out2) : "r"(out1) :: label_true, loop); 46 // CHECK: callbr { i32, i32 } asm sideeffect 47 // CHECK: to label %asm.fallthrough2 [label %label_true, label %loop] 48 // CHECK-LABEL: asm.fallthrough2: 49 return 0; 50 loop: 51 return 0; 52 label_true: 53 return 1; 54 } 55 56 int test4(int out1, int out2) { 57 // CHECK-LABEL: define{{.*}} i32 @test4( 58 // CHECK: callbr { i32, i32 } asm sideeffect "jne ${5:l}", "={si},={di},r,0,1,!i,!i 59 // CHECK: to label %asm.fallthrough [label %label_true, label %loop] 60 // CHECK-LABEL: asm.fallthrough: 61 if (out1 < out2) 62 asm volatile goto("jne %l5" : "+S"(out1), "+D"(out2) : "r"(out1) :: label_true, loop); 63 else 64 asm volatile goto("jne %l7" : "+S"(out1), "+D"(out2) : "r"(out1), "r"(out2) :: label_true, loop); 65 // CHECK: callbr { i32, i32 } asm sideeffect "jne ${7:l}", "={si},={di},r,r,0,1,!i,!i 66 // CHECK: to label %asm.fallthrough2 [label %label_true, label %loop] 67 // CHECK-LABEL: asm.fallthrough2: 68 return out1 + out2; 69 loop: 70 return -1; 71 label_true: 72 return -2; 73 } 74 75 int test5(int addr, int size, int limit) { 76 // CHECK-LABEL: define{{.*}} i32 @test5( 77 // CHECK: callbr i32 asm "add $1,$0 ; jc ${4:l} ; cmp $2,$0 ; ja ${4:l} ; ", "=r,imr,imr,0,!i 78 // CHECK: to label %asm.fallthrough [label %t_err] 79 // CHECK-LABEL: asm.fallthrough: 80 asm goto( 81 "add %1,%0 ; " 82 "jc %l[t_err] ; " 83 "cmp %2,%0 ; " 84 "ja %l[t_err] ; " 85 : "+r" (addr) 86 : "g" (size), "g" (limit) 87 : : t_err); 88 return 0; 89 t_err: 90 return 1; 91 } 92 93 int test6(int out1) { 94 // CHECK-LABEL: define{{.*}} i32 @test6( 95 // CHECK: callbr i32 asm sideeffect "testl $0, $0; testl $1, $1; jne ${3:l}", "={si},r,0,!i,!i,{{.*}} 96 // CHECK: to label %asm.fallthrough [label %label_true, label %landing] 97 // CHECK-LABEL: asm.fallthrough: 98 // CHECK-LABEL: landing: 99 int out2 = 42; 100 asm volatile goto("testl %0, %0; testl %1, %1; jne %l3" : "+S"(out2) : "r"(out1) :: label_true, landing); 101 landing: 102 return out1 + out2; 103 label_true: 104 return -2; 105 } 106 107 // test7 - For the output templates in the asm string (%0, %l2), GCC places 108 // hidden inputs tied to outputs ("+r" constraint) BEFORE labels. Test that foo 109 // is $2 (or rather ${2:l} because of the l output template) in the emitted asm 110 // string, not $1. 111 void *test7(void) { 112 // CHECK-LABEL: define{{.*}} i8* @test7( 113 // CHECK: %1 = callbr i8* asm "# $0\0A\09# ${2:l}", "=r,0,!i,~{dirflag},~{fpsr},~{flags}"(i8* %0) 114 // CHECK-NEXT: to label %asm.fallthrough [label %foo] 115 void *p = &&foo; 116 asm goto ("# %0\n\t# %l2":"+r"(p):::foo); 117 foo: 118 return p; 119 } 120 121 // test8 - the same as test7, but this time we use symbolic names rather than 122 // numbered outputs. 123 void *test8(void) { 124 // CHECK-LABEL: define{{.*}} i8* @test8( 125 // CHECK: %1 = callbr i8* asm "# $0\0A\09# ${2:l}", "=r,0,!i,~{dirflag},~{fpsr},~{flags}"(i8* %0) 126 // CHECK-NEXT: to label %asm.fallthrough [label %foo] 127 void *p = &&foo; 128 asm goto ("# %0\n\t# %l[foo]":"+r"(p):::foo); 129 foo: 130 return p; 131 } 132