
This change adds support for function linkage and visibility and related attributes. Most of the test changes are generalizations to allow 'dso_local' to be accepted where we aren't specifically testing for it. Some tests based on CIR inputs have been updated to add 'private' to function declarations where required by newly supported interfaces. The dso-local.c test has been updated to add specific tests for dso_local being set correctly, and a new test, func-linkage.cpp tests other linkage settings. This change sets `comdat` correctly in CIR, but it is not yet applied to functions when lowering to LLVM IR. That will be handled in a later change.
1186 lines
34 KiB
C++
1186 lines
34 KiB
C++
// RUN: %clang_cc1 -std=c++17 -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 -std=c++17 -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 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
|
|
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
|
|
void sw1(int a) {
|
|
switch (int b = 1; a) {
|
|
case 0:
|
|
b = b + 1;
|
|
break;
|
|
case 1:
|
|
break;
|
|
case 2: {
|
|
b = b + 1;
|
|
int yolo = 100;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z3sw1i
|
|
// CIR: cir.switch (%[[COND:.*]] : !s32i) {
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<0> : !s32i]) {
|
|
// CIR: cir.break
|
|
// CIR: cir.case(equal, [#cir.int<1> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR: cir.case(equal, [#cir.int<2> : !s32i]) {
|
|
// CIR: cir.scope {
|
|
// CIR: cir.alloca !s32i, !cir.ptr<!s32i>, ["yolo", init]
|
|
// CIR: cir.break
|
|
|
|
// LLVM: define{{.*}} void @_Z3sw1i
|
|
// LLVM: store i32 1, ptr %[[B_ADDR:.*]], align 4
|
|
// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
|
|
// LLVM: br label %[[BB7:.*]]
|
|
// LLVM: [[BB7]]:
|
|
// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
|
|
// LLVM-DAG: i32 0, label %[[CASE0:.*]]
|
|
// LLVM-DAG: i32 1, label %[[CASE1:.*]]
|
|
// LLVM-DAG: i32 2, label %[[CASE2:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE0]]:
|
|
// LLVM: %[[B:.*]] = load i32, ptr %[[B_ADDR]], align 4
|
|
// LLVM: %[[INC0:.*]] = add nsw i32 %[[B]], 1
|
|
// LLVM: store i32 %[[INC0]], ptr %[[B_ADDR]], align 4
|
|
// LLVM: br label %[[EXIT]]
|
|
// LLVM: [[CASE1]]:
|
|
// LLVM: br label %[[EXIT]]
|
|
// LLVM: [[CASE2]]:
|
|
// LLVM: br label %[[BB14:.*]]
|
|
// LLVM: [[BB14]]:
|
|
// LLVM: %[[B2:.*]] = load i32, ptr %[[B_ADDR]], align 4
|
|
// LLVM: %[[INC2:.*]] = add nsw i32 %[[B2]], 1
|
|
// LLVM: store i32 %[[INC2]], ptr %[[B_ADDR]], align 4
|
|
// LLVM: store i32 100, ptr %[[YOLO:.*]], align 4
|
|
// LLVM: br label %[[EXIT]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: br label %[[DEFAULT:.*]]
|
|
// LLVM: [[DEFAULT]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z3sw1i
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[B:.*]] = alloca i32, align 4
|
|
// OGCG: %[[YOLO:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[SW_EPILOG:.*]] [
|
|
// OGCG: i32 0, label %[[SW0:.*]]
|
|
// OGCG: i32 1, label %[[SW1:.*]]
|
|
// OGCG: i32 2, label %[[SW2:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[SW0]]:
|
|
// OGCG: %[[B_LOAD0:.*]] = load i32, ptr %[[B]], align 4
|
|
// OGCG: %[[B_INC0:.*]] = add nsw i32 %[[B_LOAD0]], 1
|
|
// OGCG: store i32 %[[B_INC0]], ptr %[[B]], align 4
|
|
// OGCG: br label %[[SW_EPILOG]]
|
|
// OGCG: [[SW1]]:
|
|
// OGCG: br label %[[SW_EPILOG]]
|
|
// OGCG: [[SW2]]:
|
|
// OGCG: %[[B_LOAD2:.*]] = load i32, ptr %[[B]], align 4
|
|
// OGCG: %[[B_INC2:.*]] = add nsw i32 %[[B_LOAD2]], 1
|
|
// OGCG: store i32 %[[B_INC2]], ptr %[[B]], align 4
|
|
// OGCG: store i32 100, ptr %[[YOLO]], align 4
|
|
// OGCG: br label %[[SW_EPILOG]]
|
|
// OGCG: [[SW_EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
void sw2(int a) {
|
|
switch (int yolo = 2; a) {
|
|
case 3:
|
|
// "fomo" has the same lifetime as "yolo"
|
|
int fomo = 0;
|
|
yolo = yolo + fomo;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z3sw2i
|
|
// CIR: cir.scope {
|
|
// CIR-NEXT: %[[YOLO:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["yolo", init]
|
|
// CIR-NEXT: %[[FOMO:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["fomo", init]
|
|
// CIR: cir.switch (%[[COND:.*]] : !s32i) {
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<3> : !s32i]) {
|
|
// CIR-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
|
|
// CIR-NEXT: cir.store{{.*}} %[[ZERO]], %[[FOMO]] : !s32i, !cir.ptr<!s32i>
|
|
|
|
// LLVM: define{{.*}} void @_Z3sw2i
|
|
// LLVM: store i32 2, ptr %[[YOLO_ADDR:.*]], align 4
|
|
// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
|
|
// LLVM: br label %[[SWITCH:.*]]
|
|
// LLVM: [[SWITCH]]:
|
|
// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
|
|
// LLVM: i32 3, label %[[CASE3:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE3]]:
|
|
// LLVM: store i32 0, ptr %[[FOMO_ADDR:.*]], align 4
|
|
// LLVM: %[[YOLO_VAL:.*]] = load i32, ptr %[[YOLO_ADDR]], align 4
|
|
// LLVM: %[[FOMO_VAL:.*]] = load i32, ptr %[[FOMO_ADDR]], align 4
|
|
// LLVM: %[[YOLO_PLUS_FOMO:.*]] = add nsw i32 %[[YOLO_VAL]], %[[FOMO_VAL]]
|
|
// LLVM: store i32 %[[YOLO_PLUS_FOMO]], ptr %[[YOLO_ADDR]], align 4
|
|
// LLVM: br label %[[EXIT]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z3sw2i
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[YOLO:.*]] = alloca i32, align 4
|
|
// OGCG: %[[FOMO:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[SW_EPILOG:.*]] [
|
|
// OGCG: i32 3, label %[[SW3:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[SW3]]:
|
|
// OGCG: %[[Y:.*]] = load i32, ptr %[[YOLO]], align 4
|
|
// OGCG: %[[F:.*]] = load i32, ptr %[[FOMO]], align 4
|
|
// OGCG: %[[SUM:.*]] = add nsw i32 %[[Y]], %[[F]]
|
|
// OGCG: store i32 %[[SUM]], ptr %[[YOLO]], align 4
|
|
// OGCG: br label %[[SW_EPILOG]]
|
|
// OGCG: [[SW_EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
void sw3(int a) {
|
|
switch (a) {
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z3sw3i
|
|
// CIR: cir.scope {
|
|
// CIR-NEXT: %[[COND:.*]] = cir.load{{.*}} %[[A:.*]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR-NEXT: cir.switch (%[[COND]] : !s32i) {
|
|
// CIR-NEXT: cir.case(default, []) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM-LABEL: define{{.*}} void @_Z3sw3i
|
|
// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
|
|
// LLVM: br label %[[SWITCH:.*]]
|
|
// LLVM: [[SWITCH]]:
|
|
// LLVM: switch i32 %[[A_VAL]], label %[[DEFAULT:.*]] [
|
|
// LLVM: ]
|
|
// LLVM: [[DEFAULT]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[EXIT:.*]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z3sw3i
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[DEFAULT:.*]] [
|
|
// OGCG: [[DEFAULT]]:
|
|
// OGCG: br label %[[EPILOG:.*]]
|
|
// OGCG: [[EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
int sw4(int a) {
|
|
switch (a) {
|
|
case 42: {
|
|
return 3;
|
|
}
|
|
default:
|
|
return 2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z3sw4i
|
|
// CIR: cir.switch (%[[COND:.*]] : !s32i) {
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<42> : !s32i]) {
|
|
// CIR-NEXT: cir.scope {
|
|
// CIR-NEXT: %[[THREE:.*]] = cir.const #cir.int<3> : !s32i
|
|
// CIR-NEXT: cir.store{{.*}} %[[THREE]], %[[RETVAL:.*]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: %[[RET3:.*]] = cir.load{{.*}} %[[RETVAL]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR-NEXT: cir.return %[[RET3]] : !s32i
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(default, []) {
|
|
// CIR-NEXT: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
|
|
// CIR-NEXT: cir.store{{.*}} %[[TWO]], %[[RETVAL]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: %[[RET2:.*]] = cir.load{{.*}} %[[RETVAL]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR-NEXT: cir.return %[[RET2]] : !s32i
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define{{.*}} i32 @_Z3sw4i
|
|
// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: %[[RET_ADDR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: br label %[[ENTRY:.*]]
|
|
// LLVM: [[ENTRY]]:
|
|
// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// LLVM: br label %[[SWITCH:.*]]
|
|
// LLVM: [[SWITCH]]:
|
|
// LLVM: switch i32 %[[A_VAL]], label %[[DEFAULT:.*]] [
|
|
// LLVM-DAG: i32 42, label %[[CASE42:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE42]]:
|
|
// LLVM: br label %[[CASE42_BODY:.*]]
|
|
// LLVM: [[CASE42_BODY]]:
|
|
// LLVM: store i32 3, ptr %[[RET_ADDR]], align 4
|
|
// LLVM: %[[RET3:.*]] = load i32, ptr %[[RET_ADDR]], align 4
|
|
// LLVM: ret i32 %[[RET3]]
|
|
// LLVM: [[DEFAULT]]:
|
|
// LLVM: store i32 2, ptr %[[RET_ADDR]], align 4
|
|
// LLVM: %[[RET2:.*]] = load i32, ptr %[[RET_ADDR]], align 4
|
|
// LLVM: ret i32 %[[RET2]]
|
|
// LLVM: [[EXIT_UNRE:.*]]:
|
|
// LLVM: store i32 0, ptr %[[RET_ADDR]], align 4
|
|
// LLVM: %[[RET0:.*]] = load i32, ptr %[[RET_ADDR]], align 4
|
|
// LLVM: ret i32 %[[RET0]]
|
|
|
|
// OGCG: define{{.*}} i32 @_Z3sw4i
|
|
// OGCG: entry:
|
|
// OGCG: %[[RETVAL:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[DEFAULT:.*]] [
|
|
// OGCG: i32 42, label %[[SW42:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[SW42]]:
|
|
// OGCG: br label %[[RETURN:.*]]
|
|
// OGCG: [[DEFAULT]]:
|
|
// OGCG: br label %[[RETURN]]
|
|
// OGCG: [[RETURN]]:
|
|
// OGCG: %[[RETVAL_LOAD:.*]] = load i32, ptr %[[RETVAL]], align 4
|
|
// OGCG: ret i32 %[[RETVAL_LOAD]]
|
|
|
|
void sw5(int a) {
|
|
switch (a) {
|
|
case 1:;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z3sw5i
|
|
// CIR: cir.switch (%[[A:.*]] : !s32i) {
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<1> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM-LABEL: define{{.*}} void @_Z3sw5i
|
|
// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: br label %[[ENTRY:.*]]
|
|
// LLVM: [[ENTRY]]:
|
|
// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// LLVM: br label %[[SWITCH:.*]]
|
|
// LLVM: [[SWITCH]]:
|
|
// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
|
|
// LLVM-DAG: i32 1, label %[[CASE1:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE1]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z3sw5i
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[SW_EPILOG:.*]] [
|
|
// OGCG: i32 1, label %[[SW1:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[SW1]]:
|
|
// OGCG: br label %[[SW_EPILOG]]
|
|
// OGCG: [[SW_EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
void sw6(int a) {
|
|
switch (a) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z3sw6i
|
|
// CIR: cir.switch (%[[A:.*]] : !s32i) {
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<0> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<1> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<2> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<3> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<4> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<5> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define{{.*}} void @_Z3sw6i
|
|
// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
|
|
// LLVM: br label %[[SWITCH:.*]]
|
|
// LLVM: [[SWITCH]]:
|
|
// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
|
|
// LLVM-DAG: i32 0, label %[[CASE0:.*]]
|
|
// LLVM-DAG: i32 1, label %[[CASE1:.*]]
|
|
// LLVM-DAG: i32 2, label %[[CASE2:.*]]
|
|
// LLVM-DAG: i32 3, label %[[CASE3:.*]]
|
|
// LLVM-DAG: i32 4, label %[[CASE4:.*]]
|
|
// LLVM-DAG: i32 5, label %[[CASE5:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE0]]:
|
|
// LLVM: br label %[[CASE0_CONT:.*]]
|
|
// LLVM: [[CASE0_CONT]]:
|
|
// LLVM: br label %[[CASE1]]
|
|
// LLVM: [[CASE1]]:
|
|
// LLVM: br label %[[CASE1_CONT:.*]]
|
|
// LLVM: [[CASE1_CONT]]:
|
|
// LLVM: br label %[[CASE2]]
|
|
// LLVM: [[CASE2]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[CASE3]]:
|
|
// LLVM: br label %[[CASE3_CONT:.*]]
|
|
// LLVM: [[CASE3_CONT]]:
|
|
// LLVM: br label %[[CASE4]]
|
|
// LLVM: [[CASE4]]:
|
|
// LLVM: br label %[[CASE4_CONT:.*]]
|
|
// LLVM: [[CASE4_CONT]]:
|
|
// LLVM: br label %[[CASE5]]
|
|
// LLVM: [[CASE5]]:
|
|
// LLVM: br label %[[EXIT]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z3sw6i
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: store i32 %a, ptr %[[A_ADDR]], align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[EPILOG:.*]] [
|
|
// OGCG: i32 0, label %[[BB0:.*]]
|
|
// OGCG: i32 1, label %[[BB0]]
|
|
// OGCG: i32 2, label %[[BB0]]
|
|
// OGCG: i32 3, label %[[BB1:.*]]
|
|
// OGCG: i32 4, label %[[BB1]]
|
|
// OGCG: i32 5, label %[[BB1]]
|
|
// OGCG: ]
|
|
// OGCG: [[BB0]]:
|
|
// OGCG: br label %[[EPILOG]]
|
|
// OGCG: [[BB1]]:
|
|
// OGCG: br label %[[EPILOG]]
|
|
// OGCG: [[EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
void sw7(int a) {
|
|
switch (a) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
int x;
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z3sw7i
|
|
// CIR: %[[X:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x"]
|
|
// CIR: cir.switch (%[[A:.*]] : !s32i)
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<0> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<1> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<2> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<3> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<4> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<5> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.yield
|
|
// CIR: }
|
|
|
|
// LLVM: define{{.*}} void @_Z3sw7i
|
|
// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
|
|
// LLVM: br label %[[SWITCH:.*]]
|
|
// LLVM: [[SWITCH]]:
|
|
// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
|
|
// LLVM-DAG: i32 0, label %[[CASE0:.*]]
|
|
// LLVM-DAG: i32 1, label %[[CASE1:.*]]
|
|
// LLVM-DAG: i32 2, label %[[CASE2:.*]]
|
|
// LLVM-DAG: i32 3, label %[[CASE3:.*]]
|
|
// LLVM-DAG: i32 4, label %[[CASE4:.*]]
|
|
// LLVM-DAG: i32 5, label %[[CASE5:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE0]]:
|
|
// LLVM: br label %[[CASE0_CONT:.*]]
|
|
// LLVM: [[CASE0_CONT]]:
|
|
// LLVM: br label %[[CASE1]]
|
|
// LLVM: [[CASE1]]:
|
|
// LLVM: br label %[[CASE1_CONT:.*]]
|
|
// LLVM: [[CASE1_CONT]]:
|
|
// LLVM: br label %[[CASE2]]
|
|
// LLVM: [[CASE2]]:
|
|
// LLVM: br label %[[CASE2_CONT:.*]]
|
|
// LLVM: [[CASE2_CONT]]:
|
|
// LLVM: br label %[[CASE3]]
|
|
// LLVM: [[CASE3]]:
|
|
// LLVM: br label %[[CASE3_CONT:.*]]
|
|
// LLVM: [[CASE3_CONT]]:
|
|
// LLVM: br label %[[CASE4]]
|
|
// LLVM: [[CASE4]]:
|
|
// LLVM: br label %[[CASE4_CONT:.*]]
|
|
// LLVM: [[CASE4_CONT]]:
|
|
// LLVM: br label %[[CASE5]]
|
|
// LLVM: [[CASE5]]:
|
|
// LLVM: br label %[[EXIT]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z3sw7i
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[EPILOG:.*]] [
|
|
// OGCG: i32 0, label %[[BB0:.*]]
|
|
// OGCG: i32 1, label %[[BB0]]
|
|
// OGCG: i32 2, label %[[BB0]]
|
|
// OGCG: i32 3, label %[[BB1:.*]]
|
|
// OGCG: i32 4, label %[[BB1]]
|
|
// OGCG: i32 5, label %[[BB1]]
|
|
// OGCG: ]
|
|
// OGCG: [[BB0]]:
|
|
// OGCG: br label %[[BB1]]
|
|
// OGCG: [[BB1]]:
|
|
// OGCG: br label %[[EPILOG]]
|
|
// OGCG: [[EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
|
|
void sw8(int a) {
|
|
switch (a)
|
|
{
|
|
case 3:
|
|
break;
|
|
case 4:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z3sw8i
|
|
// CIR: cir.switch (%[[A:.*]] : !s32i)
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<3> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<4> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(default, []) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define{{.*}} void @_Z3sw8i
|
|
// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
|
|
// LLVM-DAG: i32 3, label %[[CASE3:.*]]
|
|
// LLVM-DAG: i32 4, label %[[CASE4:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE3]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[CASE4]]:
|
|
// LLVM: br label %[[CASE4_CONT:.*]]
|
|
// LLVM: [[CASE4_CONT]]:
|
|
// LLVM: br label %[[DEFAULT]]
|
|
// LLVM: [[DEFAULT]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z3sw8i
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[DEFAULT:.*]] [
|
|
// OGCG: i32 3, label %[[SW3:.*]]
|
|
// OGCG: i32 4, label %[[SW4:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[SW3]]:
|
|
// OGCG: br label %[[EPILOG:.*]]
|
|
// OGCG: [[SW4]]:
|
|
// OGCG: br label %[[DEFAULT]]
|
|
// OGCG: [[DEFAULT]]:
|
|
// OGCG: br label %[[EPILOG]]
|
|
// OGCG: [[EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
void sw9(int a) {
|
|
switch (a)
|
|
{
|
|
case 3:
|
|
break;
|
|
default:
|
|
case 4:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z3sw9i
|
|
// CIR: cir.switch (%[[A:.*]] : !s32i)
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<3> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(default, []) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<4> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define{{.*}} void @_Z3sw9i
|
|
// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
|
|
// LLVM-DAG: i32 3, label %[[CASE3:.*]]
|
|
// LLVM-DAG: i32 4, label %[[CASE4:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE3]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[DEFAULT]]:
|
|
// LLVM: br label %[[DEFAULT_CONT:.*]]
|
|
// LLVM: [[DEFAULT_CONT]]:
|
|
// LLVM: br label %[[CASE4]]
|
|
// LLVM: [[CASE4]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z3sw9i
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[DEFAULT:.*]] [
|
|
// OGCG: i32 3, label %[[SW3:.*]]
|
|
// OGCG: i32 4, label %[[SW4:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[SW3]]:
|
|
// OGCG: br label %[[EPILOG:.*]]
|
|
// OGCG: [[DEFAULT]]:
|
|
// OGCG: br label %[[SW4]]
|
|
// OGCG: [[SW4]]:
|
|
// OGCG: br label %[[EPILOG]]
|
|
// OGCG: [[EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
void sw10(int a) {
|
|
switch (a)
|
|
{
|
|
case 3:
|
|
break;
|
|
case 4:
|
|
default:
|
|
case 5:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z4sw10i
|
|
// CIR: cir.switch (%[[A:.*]] : !s32i)
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<3> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<4> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(default, []) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<5> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define{{.*}} void @_Z4sw10i
|
|
// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
|
|
// LLVM-DAG: i32 3, label %[[CASE_3:.*]]
|
|
// LLVM-DAG: i32 4, label %[[CASE_4:.*]]
|
|
// LLVM-DAG: i32 5, label %[[CASE_5:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE_3]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[CASE_4]]:
|
|
// LLVM: br label %[[CASE4_CONT:.*]]
|
|
// LLVM: [[CASE4_CONT]]:
|
|
// LLVM: br label %[[DEFAULT]]
|
|
// LLVM: [[DEFAULT]]:
|
|
// LLVM: br label %[[DEFAULT_CONT:.*]]
|
|
// LLVM: [[DEFAULT_CONT]]:
|
|
// LLVM: br label %[[CASE_5]]
|
|
// LLVM: [[CASE_5]]:
|
|
// LLVM: br label %[[EXIT]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z4sw10i
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[DEFAULT:.*]] [
|
|
// OGCG: i32 3, label %[[BB3:.*]]
|
|
// OGCG: i32 4, label %[[BB4:.*]]
|
|
// OGCG: i32 5, label %[[BB5:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[BB3]]:
|
|
// OGCG: br label %[[EPILOG:.*]]
|
|
// OGCG: [[BB4]]:
|
|
// OGCG: br label %[[DEFAULT]]
|
|
// OGCG: [[DEFAULT]]:
|
|
// OGCG: br label %[[BB5]]
|
|
// OGCG: [[BB5]]:
|
|
// OGCG: br label %[[EPILOG]]
|
|
// OGCG: [[EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
void sw11(int a) {
|
|
switch (a)
|
|
{
|
|
case 3:
|
|
break;
|
|
case 4:
|
|
case 5:
|
|
default:
|
|
case 6:
|
|
case 7:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z4sw11i
|
|
// CIR: cir.switch (%[[A:.*]] : !s32i)
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<3> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<4> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<5> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(default, []) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<6> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<7> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define{{.*}} void @_Z4sw11i
|
|
// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
|
|
// LLVM-DAG: i32 3, label %[[CASE_3:.*]]
|
|
// LLVM-DAG: i32 4, label %[[CASE_4:.*]]
|
|
// LLVM-DAG: i32 5, label %[[CASE_5:.*]]
|
|
// LLVM-DAG: i32 6, label %[[CASE_6:.*]]
|
|
// LLVM-DAG: i32 7, label %[[CASE_7:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE_3]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[CASE_4]]:
|
|
// LLVM: br label %[[CASE4_CONT:.*]]
|
|
// LLVM: [[CASE4_CONT]]:
|
|
// LLVM: br label %[[CASE_5]]
|
|
// LLVM: [[CASE_5]]:
|
|
// LLVM: br label %[[CASE5_CONT:.*]]
|
|
// LLVM: [[CASE5_CONT]]:
|
|
// LLVM: br label %[[DEFAULT]]
|
|
// LLVM: [[DEFAULT]]:
|
|
// LLVM: br label %[[DEFAULT_CONT:.*]]
|
|
// LLVM: [[DEFAULT_CONT]]:
|
|
// LLVM: br label %[[CASE_6]]
|
|
// LLVM: [[CASE_6]]:
|
|
// LLVM: br label %[[CASE6_CONT:.*]]
|
|
// LLVM: [[CASE6_CONT]]:
|
|
// LLVM: br label %[[CASE_7]]
|
|
// LLVM: [[CASE_7]]:
|
|
// LLVM: br label %[[EXIT]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z4sw11i
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[DEFAULT:.*]] [
|
|
// OGCG: i32 3, label %[[BB3:.*]]
|
|
// OGCG: i32 4, label %[[BB4:.*]]
|
|
// OGCG: i32 5, label %[[BB4]]
|
|
// OGCG: i32 6, label %[[BB6:.*]]
|
|
// OGCG: i32 7, label %[[BB6]]
|
|
// OGCG: ]
|
|
// OGCG: [[BB3]]:
|
|
// OGCG: br label %[[EPILOG:.*]]
|
|
// OGCG: [[BB4]]:
|
|
// OGCG: br label %[[DEFAULT]]
|
|
// OGCG: [[DEFAULT]]:
|
|
// OGCG: br label %[[BB6]]
|
|
// OGCG: [[BB6]]:
|
|
// OGCG: br label %[[EPILOG]]
|
|
// OGCG: [[EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
void sw12(int a) {
|
|
switch (a)
|
|
{
|
|
case 3:
|
|
return;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z4sw12i
|
|
// CIR: cir.scope {
|
|
// CIR: cir.switch
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<3> : !s32i]) {
|
|
// CIR-NEXT: cir.return
|
|
// CIR-NEXT: ^bb1: // no predecessors
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define{{.*}} void @_Z4sw12i
|
|
// LLVM: switch i32 %[[COND:.*]], label %[[EXIT:.*]] [
|
|
// LLVM-DAG: i32 3, label %[[CASE_3:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE_3]]:
|
|
// LLVM: ret void
|
|
// LLVM: [[UNREACHABLE:.*]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z4sw12i
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[SW_DEFAULT:.*]] [
|
|
// OGCG: i32 3, label %[[SW3:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[SW3]]:
|
|
// OGCG: br label %[[SW_DEFAULT]]
|
|
// OGCG: [[SW_DEFAULT]]:
|
|
// OGCG: ret void
|
|
|
|
void sw13(int a, int b) {
|
|
switch (a) {
|
|
case 1:
|
|
switch (b) {
|
|
case 2:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z4sw13ii
|
|
// CIR: cir.scope {
|
|
// CIR: cir.switch
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<1> : !s32i]) {
|
|
// CIR-NEXT: cir.scope {
|
|
// CIR: cir.switch
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<2> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: }
|
|
// CIR: cir.yield
|
|
// CIR: }
|
|
// CIR: cir.return
|
|
|
|
// LLVM: define{{.*}} void @_Z4sw13ii
|
|
// LLVM: switch i32 %[[COND:.*]], label %[[OUTER_EXIT:.*]] [
|
|
// LLVM-DAG: i32 1, label %[[CASE_A_1:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE_A_1]]:
|
|
// LLVM: br label %[[LOAD_B:.*]]
|
|
// LLVM: [[LOAD_B]]:
|
|
// LLVM: %[[B_VAL:.*]] = load i32, ptr %[[B_ADDR:.*]], align 4
|
|
// LLVM: br label %[[INNER_SWITCH:.*]]
|
|
// LLVM: [[INNER_SWITCH]]:
|
|
// LLVM: switch i32 %[[B_VAL]], label %[[INNER_EXIT:.*]] [
|
|
// LLVM-DAG: i32 2, label %[[CASE_B_2:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE_B_2]]:
|
|
// LLVM: br label %[[INNER_EXIT]]
|
|
// LLVM: [[INNER_EXIT]]:
|
|
// LLVM: br label %[[INNER_EXIT_CONT:.*]]
|
|
// LLVM: [[INNER_EXIT_CONT]]:
|
|
// LLVM: br label %[[MERGE:.*]]
|
|
// LLVM: [[MERGE]]:
|
|
// LLVM: br label %[[OUTER_EXIT]]
|
|
// LLVM: [[OUTER_EXIT]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z4sw13ii
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[B_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[EPILOG2:.*]] [
|
|
// OGCG: i32 1, label %[[SW1:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[SW1]]:
|
|
// OGCG: %[[B_VAL:.*]] = load i32, ptr %[[B_ADDR]], align 4
|
|
// OGCG: switch i32 %[[B_VAL]], label %[[EPILOG:.*]] [
|
|
// OGCG: i32 2, label %[[SW12:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[SW12]]:
|
|
// OGCG: br label %[[EPILOG]]
|
|
// OGCG: [[EPILOG]]:
|
|
// OGCG: br label %[[EPILOG2]]
|
|
// OGCG: [[EPILOG2]]:
|
|
// OGCG: ret void
|
|
|
|
void sw14(int x) {
|
|
switch (x) {
|
|
case 1:
|
|
case 2:
|
|
case 3 ... 6:
|
|
case 7:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z4sw14i
|
|
// CIR: cir.switch
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<1> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<2> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(range, [#cir.int<3> : !s32i, #cir.int<6> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<7> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(default, []) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define{{.*}} void @_Z4sw14i
|
|
// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
|
|
// LLVM-DAG: i32 1, label %[[CASE1:.*]]
|
|
// LLVM-DAG: i32 2, label %[[CASE2:.*]]
|
|
// LLVM-DAG: i32 3, label %[[CASE3_TO_6:.*]]
|
|
// LLVM-DAG: i32 4, label %[[CASE3_TO_6]]
|
|
// LLVM-DAG: i32 5, label %[[CASE3_TO_6]]
|
|
// LLVM-DAG: i32 6, label %[[CASE3_TO_6]]
|
|
// LLVM-DAG: i32 7, label %[[CASE7:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE1]]:
|
|
// LLVM: br label %[[AFTER1:.*]]
|
|
// LLVM: [[AFTER1]]:
|
|
// LLVM: br label %[[CASE2]]
|
|
// LLVM: [[CASE2]]:
|
|
// LLVM: br label %[[AFTER2:.*]]
|
|
// LLVM: [[AFTER2]]:
|
|
// LLVM: br label %[[CASE3_TO_6]]
|
|
// LLVM: [[CASE3_TO_6]]:
|
|
// LLVM: br label %[[AFTER3_6:.*]]
|
|
// LLVM: [[AFTER3_6]]:
|
|
// LLVM: br label %[[CASE7]]
|
|
// LLVM: [[CASE7]]:
|
|
// LLVM: br label %[[EXIT1:.*]]
|
|
// LLVM: [[DEFAULT]]:
|
|
// LLVM: br label %[[EXIT1]]
|
|
// LLVM: [[EXIT1]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z4sw14i
|
|
// OGCG: entry:
|
|
// OGCG: %[[X_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: store i32 %x, ptr %[[X_ADDR]], align 4
|
|
// OGCG: %[[X_VAL:.*]] = load i32, ptr %[[X_ADDR]], align 4
|
|
// OGCG: switch i32 %[[X_VAL]], label %[[DEFAULT:.*]] [
|
|
// OGCG-DAG: i32 1, label %[[BB1:.*]]
|
|
// OGCG-DAG: i32 2, label %[[BB1]]
|
|
// OGCG-DAG: i32 3, label %[[BB2:.*]]
|
|
// OGCG-DAG: i32 4, label %[[BB2]]
|
|
// OGCG-DAG: i32 5, label %[[BB2]]
|
|
// OGCG-DAG: i32 6, label %[[BB2]]
|
|
// OGCG-DAG: i32 7, label %[[BB3:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[BB1]]:
|
|
// OGCG: br label %[[BB2]]
|
|
// OGCG: [[BB2]]:
|
|
// OGCG: br label %[[BB3]]
|
|
// OGCG: [[BB3]]:
|
|
// OGCG: br label %[[EPILOG:.*]]
|
|
// OGCG: [[DEFAULT]]:
|
|
// OGCG: br label %[[EPILOG]]
|
|
// OGCG: [[EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
void sw15(int x) {
|
|
int y;
|
|
switch (x) {
|
|
case 1:
|
|
case 2:
|
|
y = 0;
|
|
case 3:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func{{.*}} @_Z4sw15i
|
|
// CIR: %[[Y:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["y"]
|
|
// CIR: cir.switch
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<1> : !s32i]) {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<2> : !s32i]) {
|
|
// CIR-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
|
|
// CIR-NEXT: cir.store{{.*}} %[[ZERO]], %[[Y]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(equal, [#cir.int<3> : !s32i]) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.case(default, []) {
|
|
// CIR-NEXT: cir.break
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define{{.*}} void @_Z4sw15i
|
|
// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
|
|
// LLVM-DAG: i32 1, label %[[CASE1:.*]]
|
|
// LLVM-DAG: i32 2, label %[[CASE2:.*]]
|
|
// LLVM-DAG: i32 3, label %[[CASE3:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE1]]:
|
|
// LLVM: br label %[[CASE1_CONT:.*]]
|
|
// LLVM: [[CASE1_CONT]]:
|
|
// LLVM: br label %[[CASE2]]
|
|
// LLVM: [[CASE2]]:
|
|
// LLVM: store i32 0, ptr %[[Y_ADDR:.*]], align 4
|
|
// LLVM: br label %[[CASE2_CONT:.*]]
|
|
// LLVM: [[CASE2_CONT]]:
|
|
// LLVM: br label %[[CASE3]]
|
|
// LLVM: [[CASE3]]:
|
|
// LLVM: br label %[[EXIT:.*]]
|
|
// LLVM: [[DEFAULT]]:
|
|
// LLVM: br label %[[EXIT]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: br label %[[RET:.*]]
|
|
// LLVM: [[RET]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z4sw15i
|
|
// OGCG: entry:
|
|
// OGCG: %[[X_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[Y:.*]] = alloca i32, align 4
|
|
// OGCG: store i32 %x, ptr %[[X_ADDR]], align 4
|
|
// OGCG: %[[X_VAL:.*]] = load i32, ptr %[[X_ADDR]], align 4
|
|
// OGCG: switch i32 %[[X_VAL]], label %[[DEFAULT:.*]] [
|
|
// OGCG-DAG: i32 1, label %[[BB0:.*]]
|
|
// OGCG-DAG: i32 2, label %[[BB0]]
|
|
// OGCG-DAG: i32 3, label %[[BB1:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[BB0]]:
|
|
// OGCG: store i32 0, ptr %[[Y]], align 4
|
|
// OGCG: br label %[[BB1]]
|
|
// OGCG: [[BB1]]:
|
|
// OGCG: br label %[[EPILOG:.*]]
|
|
// OGCG: [[DEFAULT]]:
|
|
// OGCG: br label %[[EPILOG]]
|
|
// OGCG: [[EPILOG]]:
|
|
// OGCG: ret void
|
|
|
|
int nested_switch(int a) {
|
|
switch (int b = 1; a) {
|
|
case 0:
|
|
b = b + 1;
|
|
case 1:
|
|
return b;
|
|
case 2: {
|
|
b = b + 1;
|
|
if (a > 1000) {
|
|
case 9:
|
|
b = a + b;
|
|
}
|
|
if (a > 500) {
|
|
case 7:
|
|
return a + b;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// CIR: cir.switch (%[[COND:.*]] : !s32i) {
|
|
// CIR: cir.case(equal, [#cir.int<0> : !s32i]) {
|
|
// CIR: cir.yield
|
|
// CIR: }
|
|
// CIR: cir.case(equal, [#cir.int<1> : !s32i]) {
|
|
// CIR: cir.return
|
|
// CIR: }
|
|
// CIR: cir.case(equal, [#cir.int<2> : !s32i]) {
|
|
// CIR: cir.scope {
|
|
// CIR: cir.scope {
|
|
// CIR: cir.if
|
|
// CIR: cir.case(equal, [#cir.int<9> : !s32i]) {
|
|
// CIR: cir.yield
|
|
// CIR: cir.scope {
|
|
// CIR: cir.if
|
|
// CIR: cir.case(equal, [#cir.int<7> : !s32i]) {
|
|
// CIR: cir.return
|
|
|
|
// LLVM: define{{.*}} i32 @_Z13nested_switchi
|
|
// LLVM: %[[B_ADDR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: %[[RES_ADDR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: store i32 %[[ARG:.*]], ptr %[[A_ADDR]], align 4
|
|
// LLVM: br label %[[ENTRY:.*]]
|
|
// LLVM: [[ENTRY]]:
|
|
// LLVM: store i32 1, ptr %[[B_ADDR]], align 4
|
|
// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// LLVM: br label %[[SWITCH:.*]]
|
|
// LLVM: [[SWITCH]]:
|
|
// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
|
|
// LLVM-DAG: i32 0, label %[[CASE0:.*]]
|
|
// LLVM-DAG: i32 1, label %[[CASE1:.*]]
|
|
// LLVM-DAG: i32 2, label %[[CASE2:.*]]
|
|
// LLVM-DAG: i32 9, label %[[CASE9:.*]]
|
|
// LLVM-DAG: i32 7, label %[[CASE7:.*]]
|
|
// LLVM: ]
|
|
// LLVM: [[CASE0]]:
|
|
// LLVM: %[[B0:.*]] = load i32, ptr %[[B_ADDR]], align 4
|
|
// LLVM: %[[B1:.*]] = add nsw i32 %[[B0]], 1
|
|
// LLVM: store i32 %[[B1]], ptr %[[B_ADDR]], align 4
|
|
// LLVM: br label %[[CASE0_CONT:.*]]
|
|
// LLVM: [[CASE0_CONT]]:
|
|
// LLVM: br label %[[CASE1]]
|
|
// LLVM: [[CASE1]]:
|
|
// LLVM: %[[B1a:.*]] = load i32, ptr %[[B_ADDR]], align 4
|
|
// LLVM: store i32 %[[B1a]], ptr %[[RES_ADDR]], align 4
|
|
// LLVM: %[[RET1:.*]] = load i32, ptr %[[RES_ADDR]], align 4
|
|
// LLVM: ret i32 %[[RET1]]
|
|
// LLVM: [[CASE2]]:
|
|
// LLVM: br label %[[CASE2_BODY:.*]]
|
|
// LLVM: [[CASE2_BODY]]:
|
|
// LLVM: %[[B2:.*]] = load i32, ptr %[[B_ADDR]], align 4
|
|
// LLVM: %[[B3:.*]] = add nsw i32 %[[B2]], 1
|
|
// LLVM: store i32 %[[B3]], ptr %[[B_ADDR]], align 4
|
|
// LLVM: br label %[[CASE2_CONT:.*]]
|
|
// LLVM: [[CASE9]]:
|
|
// LLVM: %[[A9:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// LLVM: %[[B4:.*]] = load i32, ptr %[[B_ADDR]], align 4
|
|
// LLVM: %[[SUM9:.*]] = add nsw i32 %[[A9]], %[[B4]]
|
|
// LLVM: store i32 %[[SUM9]], ptr %[[B_ADDR]], align 4
|
|
// LLVM: br label %[[CASE2_CONT1:.*]]
|
|
// LLVM: [[CASE7]]:
|
|
// LLVM: %[[A7:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// LLVM: %[[B5:.*]] = load i32, ptr %[[B_ADDR]], align 4
|
|
// LLVM: %[[SUM7:.*]] = add nsw i32 %[[A7]], %[[B5]]
|
|
// LLVM: store i32 %[[SUM7]], ptr %[[RES_ADDR]], align 4
|
|
// LLVM: %[[RET7:.*]] = load i32, ptr %[[RES_ADDR]], align 4
|
|
// LLVM: ret i32 %[[RET7]]
|
|
// LLVM: [[EXIT]]:
|
|
// LLVM: store i32 0, ptr %[[RES_ADDR]], align 4
|
|
// LLVM: %[[RET0:.*]] = load i32, ptr %[[RES_ADDR]], align 4
|
|
// LLVM: ret i32 %[[RET0]]
|
|
|
|
// OGCG: define{{.*}} i32 @_Z13nested_switchi
|
|
// OGCG: entry:
|
|
// OGCG: %[[RETVAL:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[B:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: switch i32 %[[A_VAL]], label %[[EPILOG:.*]] [
|
|
// OGCG: i32 0, label %[[SW0:.*]]
|
|
// OGCG: i32 1, label %[[SW1:.*]]
|
|
// OGCG: i32 2, label %[[SW2:.*]]
|
|
// OGCG: i32 9, label %[[SW4:.*]]
|
|
// OGCG: i32 7, label %[[SW8:.*]]
|
|
// OGCG: ]
|
|
// OGCG: [[SW0]]:
|
|
// OGCG: %[[B_VAL0:.*]] = load i32, ptr %[[B]], align 4
|
|
// OGCG: %[[ADD0:.*]] = add nsw i32 %[[B_VAL0]], 1
|
|
// OGCG: br label %[[SW1]]
|
|
// OGCG: [[SW1]]:
|
|
// OGCG: %[[B_VAL1:.*]] = load i32, ptr %[[B]], align 4
|
|
// OGCG: br label %[[RETURN:.*]]
|
|
// OGCG: [[SW2]]:
|
|
// OGCG: %[[B_VAL2:.*]] = load i32, ptr %[[B]], align 4
|
|
// OGCG: %[[ADD2:.*]] = add nsw i32 %[[B_VAL2]], 1
|
|
// OGCG: %[[A_VAL2:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: %[[CMP1000:.*]] = icmp sgt i32 %[[A_VAL2]], 1000
|
|
// OGCG: br i1 %[[CMP1000]], label %[[IFTHEN:.*]], label %[[IFEND:.*]]
|
|
// OGCG: [[IFTHEN]]:
|
|
// OGCG: br label %[[SW4]]
|
|
// OGCG: [[SW4]]:
|
|
// OGCG: %[[A_VAL4:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: %[[B_VAL4:.*]] = load i32, ptr %[[B]], align 4
|
|
// OGCG: %[[ADD4:.*]] = add nsw i32 %[[A_VAL4]], %[[B_VAL4]]
|
|
// OGCG: br label %[[IFEND]]
|
|
// OGCG: [[IFEND]]:
|
|
// OGCG: %[[A_VAL5:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: %[[CMP500:.*]] = icmp sgt i32 %[[A_VAL5]], 500
|
|
// OGCG: br i1 %[[CMP500]], label %[[IFTHEN7:.*]], label %[[IFEND10:.*]]
|
|
// OGCG: [[IFTHEN7]]:
|
|
// OGCG: br label %[[SW8]]
|
|
// OGCG: [[SW8]]:
|
|
// OGCG: %[[A_VAL8:.*]] = load i32, ptr %[[A_ADDR]], align 4
|
|
// OGCG: %[[B_VAL8:.*]] = load i32, ptr %[[B]], align 4
|
|
// OGCG: %[[ADD8:.*]] = add nsw i32 %[[A_VAL8]], %[[B_VAL8]]
|
|
// OGCG: br label %[[RETURN]]
|
|
// OGCG: [[IFEND10]]:
|
|
// OGCG: br label %[[EPILOG]]
|
|
// OGCG: [[EPILOG]]:
|