// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// REQUIRES: x86-registered-target
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s

// CHECK-LABEL: @test0(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RET:%.*]] = alloca i32, align 4
// CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
// CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
// CHECK:       asm.fallthrough:
// CHECK-NEXT:    store i32 [[TMP0]], ptr [[RET]], align 4
// CHECK-NEXT:    store i32 42, ptr [[RET]], align 4
// CHECK-NEXT:    br label [[Z:%.*]]
// CHECK:       z:
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RET]], align 4
// CHECK-NEXT:    ret i32 [[TMP1]]
// CHECK:       z.split:
// CHECK-NEXT:    store i32 [[TMP0]], ptr [[RET]], align 4
// CHECK-NEXT:    br label [[Z]]
//
int test0 (void) {
  int ret;
  asm goto ("" : "=r"(ret):::z);
  ret = 42;
z:
  return ret;
}

// CHECK-LABEL: @test1(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RET:%.*]] = alloca i32, align 4
// CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
// CHECK-NEXT:    [[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
// CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
// CHECK:       asm.fallthrough:
// CHECK-NEXT:    [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
// CHECK-NEXT:    [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
// CHECK-NEXT:    store i32 [[ASMRESULT]], ptr [[RET]], align 4
// CHECK-NEXT:    store i32 [[ASMRESULT1]], ptr [[B]], align 4
// CHECK-NEXT:    store i32 42, ptr [[RET]], align 4
// CHECK-NEXT:    br label [[Z:%.*]]
// CHECK:       z:
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RET]], align 4
// CHECK-NEXT:    ret i32 [[TMP1]]
// CHECK:       z.split:
// CHECK-NEXT:    [[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
// CHECK-NEXT:    [[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
// CHECK-NEXT:    store i32 [[ASMRESULT2]], ptr [[RET]], align 4
// CHECK-NEXT:    store i32 [[ASMRESULT3]], ptr [[B]], align 4
// CHECK-NEXT:    br label [[Z]]
//
int test1 (void) {
  int ret, b;
  asm goto ("" : "=r"(ret), "=r"(b):::z);
  ret = 42;
z:
  return ret;
}

// CHECK-LABEL: @test2(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RET:%.*]] = alloca i32, align 4
// CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
// CHECK-NEXT:    [[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
// CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
// CHECK:       asm.fallthrough:
// CHECK-NEXT:    [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
// CHECK-NEXT:    [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
// CHECK-NEXT:    store i32 [[ASMRESULT]], ptr [[RET]], align 4
// CHECK-NEXT:    store i32 [[ASMRESULT1]], ptr [[B]], align 4
// CHECK-NEXT:    [[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
// CHECK-NEXT:    to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
// CHECK:       asm.fallthrough4:
// CHECK-NEXT:    [[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
// CHECK-NEXT:    [[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
// CHECK-NEXT:    store i32 [[ASMRESULT5]], ptr [[RET]], align 4
// CHECK-NEXT:    store i32 [[ASMRESULT6]], ptr [[B]], align 4
// CHECK-NEXT:    br label [[Z:%.*]]
// CHECK:       z:
// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[RET]], align 4
// CHECK-NEXT:    ret i32 [[TMP2]]
// CHECK:       z.split:
// CHECK-NEXT:    [[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
// CHECK-NEXT:    [[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
// CHECK-NEXT:    store i32 [[ASMRESULT2]], ptr [[RET]], align 4
// CHECK-NEXT:    store i32 [[ASMRESULT3]], ptr [[B]], align 4
// CHECK-NEXT:    br label [[Z]]
// CHECK:       z.split9:
// CHECK-NEXT:    [[ASMRESULT7:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
// CHECK-NEXT:    [[ASMRESULT8:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
// CHECK-NEXT:    store i32 [[ASMRESULT7]], ptr [[RET]], align 4
// CHECK-NEXT:    store i32 [[ASMRESULT8]], ptr [[B]], align 4
// CHECK-NEXT:    br label [[Z]]
//
int test2 (void) {
  int ret, b;
  asm goto ("" : "=r"(ret), "=r"(b):::z);
  asm goto ("" : "=r"(ret), "=r"(b):::z);
z:
  return ret;
}
// CHECK-LABEL: @test3(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
// CHECK-NEXT:    [[OUT1_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT:    store i32 [[OUT1:%.*]], ptr [[OUT1_ADDR]], align 4
// CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
// CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label [[LABEL_TRUE_SPLIT:%.*]], label %loop.split], !srcloc !6
// CHECK:       asm.fallthrough:
// CHECK-NEXT:    store i32 [[TMP0]], ptr [[OUT1_ADDR]], align 4
// CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
// CHECK-NEXT:    br label [[RETURN:%.*]]
// CHECK:       label_true.split:
// CHECK-NEXT:    store i32 [[TMP0]], ptr [[OUT1_ADDR]], align 4
// CHECK-NEXT:    br label [[LABEL_TRUE:%.*]]
// CHECK:       loop.split:
// CHECK-NEXT:    store i32 [[TMP0]], ptr [[OUT1_ADDR]], align 4
// CHECK-NEXT:    br label [[LOOP:%.*]]
// CHECK:       loop:
// CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
// CHECK-NEXT:    br label [[RETURN]]
// CHECK:       label_true:
// CHECK-NEXT:    store i32 1, ptr [[RETVAL]], align 4
// CHECK-NEXT:    br label [[RETURN]]
// CHECK:       return:
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[RETVAL]], align 4
// CHECK-NEXT:    ret i32 [[TMP1]]
//
int test3 (int out1) {
  asm goto("" : "=r"(out1)::: label_true, loop);
  return 0;
loop:
  return 0;
label_true:
  return 1;
}

// CHECK-LABEL: @test4(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[X:%.*]] = alloca i32, align 4
// CHECK-NEXT:    br label [[FOO:%.*]]
// CHECK:       foo:
// CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
// CHECK-NEXT:    to label [[ASM_FALLTHROUGH:%.*]] [label %foo.split], !srcloc !7
// CHECK:       asm.fallthrough:
// CHECK-NEXT:    store i32 [[TMP0]], ptr [[X]], align 4
// CHECK-NEXT:    ret void
// CHECK:       foo.split:
// CHECK-NEXT:    store i32 [[TMP0]], ptr [[X]], align 4
// CHECK-NEXT:    br label [[FOO]]
//
void test4 (void) {
  int x;
foo:
  asm goto ("" : "=r"(x):::foo);
}
