xref: /llvm-project/clang/test/CodeGen/asm-goto2.c (revision 329ef60f3e21fd6845e8e8b0da405cae7eb27267)
1*329ef60fSNick Desaulniers // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2*329ef60fSNick Desaulniers // REQUIRES: x86-registered-target
3*329ef60fSNick Desaulniers // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
4*329ef60fSNick Desaulniers 
5*329ef60fSNick Desaulniers // CHECK-LABEL: @test0(
6*329ef60fSNick Desaulniers // CHECK-NEXT:  entry:
7*329ef60fSNick Desaulniers // CHECK-NEXT:    [[RET:%.*]] = alloca i32, align 4
8*329ef60fSNick Desaulniers // CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
9*329ef60fSNick Desaulniers // CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
10*329ef60fSNick Desaulniers // CHECK:       asm.fallthrough:
11*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[TMP0]], ptr [[RET]], align 4
12*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 42, ptr [[RET]], align 4
13*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[Z:%.*]]
14*329ef60fSNick Desaulniers // CHECK:       z:
15*329ef60fSNick Desaulniers // CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RET]], align 4
16*329ef60fSNick Desaulniers // CHECK-NEXT:    ret i32 [[TMP1]]
17*329ef60fSNick Desaulniers // CHECK:       z.split:
18*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[TMP0]], ptr [[RET]], align 4
19*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[Z]]
20*329ef60fSNick Desaulniers //
test0(void)21*329ef60fSNick Desaulniers int test0 (void) {
22*329ef60fSNick Desaulniers   int ret;
23*329ef60fSNick Desaulniers   asm goto ("" : "=r"(ret):::z);
24*329ef60fSNick Desaulniers   ret = 42;
25*329ef60fSNick Desaulniers z:
26*329ef60fSNick Desaulniers   return ret;
27*329ef60fSNick Desaulniers }
28*329ef60fSNick Desaulniers 
29*329ef60fSNick Desaulniers // CHECK-LABEL: @test1(
30*329ef60fSNick Desaulniers // CHECK-NEXT:  entry:
31*329ef60fSNick Desaulniers // CHECK-NEXT:    [[RET:%.*]] = alloca i32, align 4
32*329ef60fSNick Desaulniers // CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
33*329ef60fSNick Desaulniers // CHECK-NEXT:    [[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
34*329ef60fSNick Desaulniers // CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
35*329ef60fSNick Desaulniers // CHECK:       asm.fallthrough:
36*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
37*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
38*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT]], ptr [[RET]], align 4
39*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT1]], ptr [[B]], align 4
40*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 42, ptr [[RET]], align 4
41*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[Z:%.*]]
42*329ef60fSNick Desaulniers // CHECK:       z:
43*329ef60fSNick Desaulniers // CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RET]], align 4
44*329ef60fSNick Desaulniers // CHECK-NEXT:    ret i32 [[TMP1]]
45*329ef60fSNick Desaulniers // CHECK:       z.split:
46*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
47*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
48*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT2]], ptr [[RET]], align 4
49*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT3]], ptr [[B]], align 4
50*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[Z]]
51*329ef60fSNick Desaulniers //
test1(void)52*329ef60fSNick Desaulniers int test1 (void) {
53*329ef60fSNick Desaulniers   int ret, b;
54*329ef60fSNick Desaulniers   asm goto ("" : "=r"(ret), "=r"(b):::z);
55*329ef60fSNick Desaulniers   ret = 42;
56*329ef60fSNick Desaulniers z:
57*329ef60fSNick Desaulniers   return ret;
58*329ef60fSNick Desaulniers }
59*329ef60fSNick Desaulniers 
60*329ef60fSNick Desaulniers // CHECK-LABEL: @test2(
61*329ef60fSNick Desaulniers // CHECK-NEXT:  entry:
62*329ef60fSNick Desaulniers // CHECK-NEXT:    [[RET:%.*]] = alloca i32, align 4
63*329ef60fSNick Desaulniers // CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
64*329ef60fSNick Desaulniers // CHECK-NEXT:    [[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
65*329ef60fSNick Desaulniers // CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
66*329ef60fSNick Desaulniers // CHECK:       asm.fallthrough:
67*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
68*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
69*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT]], ptr [[RET]], align 4
70*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT1]], ptr [[B]], align 4
71*329ef60fSNick Desaulniers // CHECK-NEXT:    [[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
72*329ef60fSNick Desaulniers // CHECK-NEXT:    to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
73*329ef60fSNick Desaulniers // CHECK:       asm.fallthrough4:
74*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
75*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
76*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT5]], ptr [[RET]], align 4
77*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT6]], ptr [[B]], align 4
78*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[Z:%.*]]
79*329ef60fSNick Desaulniers // CHECK:       z:
80*329ef60fSNick Desaulniers // CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[RET]], align 4
81*329ef60fSNick Desaulniers // CHECK-NEXT:    ret i32 [[TMP2]]
82*329ef60fSNick Desaulniers // CHECK:       z.split:
83*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
84*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
85*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT2]], ptr [[RET]], align 4
86*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT3]], ptr [[B]], align 4
87*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[Z]]
88*329ef60fSNick Desaulniers // CHECK:       z.split9:
89*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT7:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
90*329ef60fSNick Desaulniers // CHECK-NEXT:    [[ASMRESULT8:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
91*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT7]], ptr [[RET]], align 4
92*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[ASMRESULT8]], ptr [[B]], align 4
93*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[Z]]
94*329ef60fSNick Desaulniers //
test2(void)95*329ef60fSNick Desaulniers int test2 (void) {
96*329ef60fSNick Desaulniers   int ret, b;
97*329ef60fSNick Desaulniers   asm goto ("" : "=r"(ret), "=r"(b):::z);
98*329ef60fSNick Desaulniers   asm goto ("" : "=r"(ret), "=r"(b):::z);
99*329ef60fSNick Desaulniers z:
100*329ef60fSNick Desaulniers   return ret;
101*329ef60fSNick Desaulniers }
102*329ef60fSNick Desaulniers // CHECK-LABEL: @test3(
103*329ef60fSNick Desaulniers // CHECK-NEXT:  entry:
104*329ef60fSNick Desaulniers // CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
105*329ef60fSNick Desaulniers // CHECK-NEXT:    [[OUT1_ADDR:%.*]] = alloca i32, align 4
106*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[OUT1:%.*]], ptr [[OUT1_ADDR]], align 4
107*329ef60fSNick Desaulniers // CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
108*329ef60fSNick Desaulniers // CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label [[LABEL_TRUE_SPLIT:%.*]], label %loop.split], !srcloc !6
109*329ef60fSNick Desaulniers // CHECK:       asm.fallthrough:
110*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[TMP0]], ptr [[OUT1_ADDR]], align 4
111*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
112*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[RETURN:%.*]]
113*329ef60fSNick Desaulniers // CHECK:       label_true.split:
114*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[TMP0]], ptr [[OUT1_ADDR]], align 4
115*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[LABEL_TRUE:%.*]]
116*329ef60fSNick Desaulniers // CHECK:       loop.split:
117*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[TMP0]], ptr [[OUT1_ADDR]], align 4
118*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[LOOP:%.*]]
119*329ef60fSNick Desaulniers // CHECK:       loop:
120*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
121*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[RETURN]]
122*329ef60fSNick Desaulniers // CHECK:       label_true:
123*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 1, ptr [[RETVAL]], align 4
124*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[RETURN]]
125*329ef60fSNick Desaulniers // CHECK:       return:
126*329ef60fSNick Desaulniers // CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RETVAL]], align 4
127*329ef60fSNick Desaulniers // CHECK-NEXT:    ret i32 [[TMP1]]
128*329ef60fSNick Desaulniers //
test3(int out1)129*329ef60fSNick Desaulniers int test3 (int out1) {
130*329ef60fSNick Desaulniers   asm goto("" : "=r"(out1)::: label_true, loop);
131*329ef60fSNick Desaulniers   return 0;
132*329ef60fSNick Desaulniers loop:
133*329ef60fSNick Desaulniers   return 0;
134*329ef60fSNick Desaulniers label_true:
135*329ef60fSNick Desaulniers   return 1;
136*329ef60fSNick Desaulniers }
137*329ef60fSNick Desaulniers 
138*329ef60fSNick Desaulniers // CHECK-LABEL: @test4(
139*329ef60fSNick Desaulniers // CHECK-NEXT:  entry:
140*329ef60fSNick Desaulniers // CHECK-NEXT:    [[X:%.*]] = alloca i32, align 4
141*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[FOO:%.*]]
142*329ef60fSNick Desaulniers // CHECK:       foo:
143*329ef60fSNick Desaulniers // CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
144*329ef60fSNick Desaulniers // CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label %foo.split], !srcloc !7
145*329ef60fSNick Desaulniers // CHECK:       asm.fallthrough:
146*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[TMP0]], ptr [[X]], align 4
147*329ef60fSNick Desaulniers // CHECK-NEXT:    ret void
148*329ef60fSNick Desaulniers // CHECK:       foo.split:
149*329ef60fSNick Desaulniers // CHECK-NEXT:    store i32 [[TMP0]], ptr [[X]], align 4
150*329ef60fSNick Desaulniers // CHECK-NEXT:    br label [[FOO]]
151*329ef60fSNick Desaulniers //
test4(void)152*329ef60fSNick Desaulniers void test4 (void) {
153*329ef60fSNick Desaulniers   int x;
154*329ef60fSNick Desaulniers foo:
155*329ef60fSNick Desaulniers   asm goto ("" : "=r"(x):::foo);
156*329ef60fSNick Desaulniers }
157