// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir // RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll // RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll // RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG int shouldNotGenBranchRet(int x) { if (x > 5) goto err; return 0; err: return -1; } // CIR: cir.func dso_local @_Z21shouldNotGenBranchReti // CIR: cir.if {{.*}} { // CIR: cir.goto "err" // CIR: } // CIR: [[ZERO:%.*]] = cir.const #cir.int<0> : !s32i // CIR: cir.store [[ZERO]], [[RETVAL:%.*]] : !s32i, !cir.ptr // CIR: cir.br ^bb1 // CIR: ^bb1: // CIR: [[RET:%.*]] = cir.load [[RETVAL]] : !cir.ptr, !s32i // CIR: cir.return [[RET]] : !s32i // CIR: ^bb2: // CIR: cir.label "err" // CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s32i // CIR: [[MINUS:%.*]] = cir.unary(minus, [[ONE]]) nsw : !s32i, !s32i // CIR: cir.store [[MINUS]], [[RETVAL]] : !s32i, !cir.ptr // CIR: cir.br ^bb1 // LLVM: define dso_local i32 @_Z21shouldNotGenBranchReti // LLVM: [[COND:%.*]] = load i32, ptr {{.*}}, align 4 // LLVM: [[CMP:%.*]] = icmp sgt i32 [[COND]], 5 // LLVM: br i1 [[CMP]], label %[[IFTHEN:.*]], label %[[IFEND:.*]] // LLVM: [[IFTHEN]]: // LLVM: br label %[[ERR:.*]] // LLVM: [[IFEND]]: // LLVM: br label %[[BB9:.*]] // LLVM: [[BB9]]: // LLVM: store i32 0, ptr %[[RETVAL:.*]], align 4 // LLVM: br label %[[BBRET:.*]] // LLVM: [[BBRET]]: // LLVM: [[RET:%.*]] = load i32, ptr %[[RETVAL]], align 4 // LLVM: ret i32 [[RET]] // LLVM: [[ERR]]: // LLVM: store i32 -1, ptr %[[RETVAL]], align 4 // LLVM: br label %10 // OGCG: define dso_local noundef i32 @_Z21shouldNotGenBranchReti // OGCG: if.then: // OGCG: br label %err // OGCG: if.end: // OGCG: br label %return // OGCG: err: // OGCG: br label %return // OGCG: return: int shouldGenBranch(int x) { if (x > 5) goto err; x++; err: return -1; } // CIR: cir.func dso_local @_Z15shouldGenBranchi // CIR: cir.if {{.*}} { // CIR: cir.goto "err" // CIR: } // CIR: cir.br ^bb1 // CIR: ^bb1: // CIR: cir.label "err" // LLVM: define dso_local i32 @_Z15shouldGenBranchi // LLVM: br i1 [[CMP:%.*]], label %[[IFTHEN:.*]], label %[[IFEND:.*]] // LLVM: [[IFTHEN]]: // LLVM: br label %[[ERR:.*]] // LLVM: [[IFEND]]: // LLVM: br label %[[BB9:.*]] // LLVM: [[BB9]]: // LLVM: br label %[[ERR]] // LLVM: [[ERR]]: // LLVM: ret i32 [[RET:%.*]] // OGCG: define dso_local noundef i32 @_Z15shouldGenBranchi // OGCG: if.then: // OGCG: br label %err // OGCG: if.end: // OGCG: br label %err // OGCG: err: // OGCG: ret void severalLabelsInARow(int a) { int b = a; goto end1; b = b + 1; goto end2; end1: end2: b = b + 2; } // CIR: cir.func dso_local @_Z19severalLabelsInARowi // CIR: cir.goto "end1" // CIR: ^bb[[#BLK1:]] // CIR: cir.goto "end2" // CIR: ^bb[[#BLK2:]]: // CIR: cir.label "end1" // CIR: cir.br ^bb[[#BLK3:]] // CIR: ^bb[[#BLK3]]: // CIR: cir.label "end2" // LLVM: define dso_local void @_Z19severalLabelsInARowi // LLVM: br label %[[END1:.*]] // LLVM: [[UNRE:.*]]: ; No predecessors! // LLVM: br label %[[END2:.*]] // LLVM: [[END1]]: // LLVM: br label %[[END2]] // LLVM: [[END2]]: // LLVM: ret // OGCG: define dso_local void @_Z19severalLabelsInARowi // OGCG: br label %end1 // OGCG: end1: // OGCG: br label %end2 // OGCG: end2: // OGCG: ret void severalGotosInARow(int a) { int b = a; goto end; goto end; end: b = b + 2; } // CIR: cir.func dso_local @_Z18severalGotosInARowi // CIR: cir.goto "end" // CIR: ^bb[[#BLK1:]]: // CIR: cir.goto "end" // CIR: ^bb[[#BLK2:]]: // CIR: cir.label "end" // LLVM: define dso_local void @_Z18severalGotosInARowi // LLVM: br label %[[END:.*]] // LLVM: [[UNRE:.*]]: ; No predecessors! // LLVM: br label %[[END]] // LLVM: [[END]]: // LLVM: ret void // OGCG: define dso_local void @_Z18severalGotosInARowi(i32 noundef %a) #0 { // OGCG: br label %end // OGCG: end: // OGCG: ret void extern "C" void action1(); extern "C" void action2(); extern "C" void multiple_non_case(int v) { switch (v) { default: action1(); l2: action2(); break; } } // CIR: cir.func dso_local @multiple_non_case // CIR: cir.switch // CIR: cir.case(default, []) { // CIR: cir.call @action1() // CIR: cir.br ^[[BB1:[a-zA-Z0-9]+]] // CIR: ^[[BB1]]: // CIR: cir.label // CIR: cir.call @action2() // CIR: cir.break // LLVM: define dso_local void @multiple_non_case // LLVM: [[SWDEFAULT:.*]]: // LLVM: call void @action1() // LLVM: br label %[[L2:.*]] // LLVM: [[L2]]: // LLVM: call void @action2() // LLVM: br label %[[BREAK:.*]] // OGCG: define dso_local void @multiple_non_case // OGCG: sw.default: // OGCG: call void @action1() // OGCG: br label %l2 // OGCG: l2: // OGCG: call void @action2() // OGCG: br label [[BREAK:%.*]] extern "C" void case_follow_label(int v) { switch (v) { case 1: label: case 2: action1(); break; default: action2(); goto label; } } // CIR: cir.func dso_local @case_follow_label // CIR: cir.switch // CIR: cir.case(equal, [#cir.int<1> : !s32i]) { // CIR: cir.label "label" // CIR: cir.case(equal, [#cir.int<2> : !s32i]) { // CIR: cir.call @action1() // CIR: cir.break // CIR: cir.case(default, []) { // CIR: cir.call @action2() // CIR: cir.goto "label" // LLVM: define dso_local void @case_follow_label // LLVM: switch i32 {{.*}}, label %[[SWDEFAULT:.*]] [ // LLVM: i32 1, label %[[LABEL:.*]] // LLVM: i32 2, label %[[CASE2:.*]] // LLVM: ] // LLVM: [[LABEL]]: // LLVM: br label %[[CASE2]] // LLVM: [[CASE2]]: // LLVM: call void @action1() // LLVM: br label %[[BREAK:.*]] // LLVM: [[BREAK]]: // LLVM: br label %[[END:.*]] // LLVM: [[SWDEFAULT]]: // LLVM: call void @action2() // LLVM: br label %[[LABEL]] // LLVM: [[END]]: // LLVM: br label %[[RET:.*]] // LLVM: [[RET]]: // LLVM: ret void // OGCG: define dso_local void @case_follow_label // OGCG: sw.bb: // OGCG: br label %label // OGCG: label: // OGCG: br label %sw.bb1 // OGCG: sw.bb1: // OGCG: call void @action1() // OGCG: br label %sw.epilog // OGCG: sw.default: // OGCG: call void @action2() // OGCG: br label %label // OGCG: sw.epilog: // OGCG: ret void extern "C" void default_follow_label(int v) { switch (v) { case 1: case 2: action1(); break; label: default: action2(); goto label; } } // CIR: cir.func dso_local @default_follow_label // CIR: cir.switch // CIR: cir.case(equal, [#cir.int<1> : !s32i]) { // CIR: cir.yield // CIR: cir.case(equal, [#cir.int<2> : !s32i]) { // CIR: cir.call @action1() // CIR: cir.break // CIR: cir.label "label" // CIR: cir.case(default, []) { // CIR: cir.call @action2() // CIR: cir.goto "label" // LLVM: define dso_local void @default_follow_label // LLVM: [[CASE1:.*]]: // LLVM: br label %[[BB8:.*]] // LLVM: [[BB8]]: // LLVM: br label %[[CASE2:.*]] // LLVM: [[CASE2]]: // LLVM: call void @action1() // LLVM: br label %[[BREAK:.*]] // LLVM: [[LABEL:.*]]: // LLVM: br label %[[SWDEFAULT:.*]] // LLVM: [[SWDEFAULT]]: // LLVM: call void @action2() // LLVM: br label %[[BB9:.*]] // LLVM: [[BB9]]: // LLVM: br label %[[LABEL]] // LLVM: [[BREAK]]: // LLVM: br label %[[RET:.*]] // LLVM: [[RET]]: // LLVM: ret void // OGCG: define dso_local void @default_follow_label // OGCG: sw.bb: // OGCG: call void @action1() // OGCG: br label %sw.epilog // OGCG: label: // OGCG: br label %sw.default // OGCG: sw.default: // OGCG: call void @action2() // OGCG: br label %label // OGCG: sw.epilog: // OGCG: ret void