319 lines · plain
1// RUN: cir-opt %s -cir-flatten-cfg -o - | FileCheck %s2 3!s8i = !cir.int<s, 8>4!s32i = !cir.int<s, 32>5!s64i = !cir.int<s, 64>6 7module {8 cir.func @shouldFlatSwitchWithDefault(%arg0: !s8i) {9 cir.switch (%arg0 : !s8i) {10 cir.case (equal, [#cir.int<1> : !s8i]) {11 cir.break12 }13 cir.case (default, []) {14 cir.break15 }16 cir.yield17 }18 cir.return19 }20// CHECK: cir.func{{.*}} @shouldFlatSwitchWithDefault(%arg0: !s8i) {21// CHECK: cir.switch.flat %arg0 : !s8i, ^bb[[#DEFAULT:]] [22// CHECK: 1: ^bb[[#CASE1:]]23// CHECK: ]24// CHECK: ^bb[[#CASE1]]:25// CHECK: cir.br ^bb[[#EXIT:]]26// CHECK: ^bb[[#DEFAULT]]:27// CHECK: cir.br ^bb[[#EXIT]]28// CHECK: ^bb[[#EXIT]]:29// CHECK: cir.return30// CHECK: }31 32 cir.func @shouldFlatSwitchWithoutDefault(%arg0: !s32i) {33 cir.switch (%arg0 : !s32i) {34 cir.case (equal, [#cir.int<1> : !s32i]) {35 cir.break36 }37 cir.yield38 }39 cir.return40 }41// CHECK: cir.func{{.*}} @shouldFlatSwitchWithoutDefault(%arg0: !s32i) {42// CHECK: cir.switch.flat %arg0 : !s32i, ^bb[[#EXIT:]] [43// CHECK: 1: ^bb[[#CASE1:]]44// CHECK: ]45// CHECK: ^bb[[#CASE1]]:46// CHECK: cir.br ^bb[[#EXIT]]47// CHECK: ^bb[[#EXIT]]:48// CHECK: cir.return49// CHECK: }50 51 52 cir.func @shouldFlatSwitchWithImplicitFallthrough(%arg0: !s64i) {53 cir.switch (%arg0 : !s64i) {54 cir.case (anyof, [#cir.int<1> : !s64i, #cir.int<2> : !s64i]) {55 cir.break56 }57 cir.yield58 }59 cir.return60 }61// CHECK: cir.func{{.*}} @shouldFlatSwitchWithImplicitFallthrough(%arg0: !s64i) {62// CHECK: cir.switch.flat %arg0 : !s64i, ^bb[[#EXIT:]] [63// CHECK: 1: ^bb[[#CASE1N2:]],64// CHECK: 2: ^bb[[#CASE1N2]]65// CHECK: ]66// CHECK: ^bb[[#CASE1N2]]:67// CHECK: cir.br ^bb[[#EXIT]]68// CHECK: ^bb[[#EXIT]]:69// CHECK: cir.return70// CHECK: }71 72 73 74 cir.func @shouldFlatSwitchWithExplicitFallthrough(%arg0: !s64i) {75 cir.switch (%arg0 : !s64i) {76 cir.case (equal, [#cir.int<1> : !s64i]) { // case 1 has its own region77 cir.yield // fallthrough to case 278 }79 cir.case (equal, [#cir.int<2> : !s64i]) {80 cir.break81 }82 cir.yield83 }84 cir.return85 }86// CHECK: cir.func{{.*}} @shouldFlatSwitchWithExplicitFallthrough(%arg0: !s64i) {87// CHECK: cir.switch.flat %arg0 : !s64i, ^bb[[#EXIT:]] [88// CHECK: 1: ^bb[[#CASE1:]],89// CHECK: 2: ^bb[[#CASE2:]]90// CHECK: ]91// CHECK: ^bb[[#CASE1]]:92// CHECK: cir.br ^bb[[#CASE2]]93// CHECK: ^bb[[#CASE2]]:94// CHECK: cir.br ^bb[[#EXIT]]95// CHECK: ^bb[[#EXIT]]:96// CHECK: cir.return97// CHECK: }98 99 cir.func @shouldFlatSwitchWithFallthroughToExit(%arg0: !s64i) {100 cir.switch (%arg0 : !s64i) {101 cir.case (equal, [#cir.int<1> : !s64i]) {102 cir.yield // fallthrough to exit103 }104 cir.yield105 }106 cir.return107 }108// CHECK: cir.func{{.*}} @shouldFlatSwitchWithFallthroughToExit(%arg0: !s64i) {109// CHECK: cir.switch.flat %arg0 : !s64i, ^bb[[#EXIT:]] [110// CHECK: 1: ^bb[[#CASE1:]]111// CHECK: ]112// CHECK: ^bb[[#CASE1]]:113// CHECK: cir.br ^bb[[#EXIT]]114// CHECK: ^bb[[#EXIT]]:115// CHECK: cir.return116// CHECK: }117 118 cir.func @shouldDropEmptySwitch(%arg0: !s64i) {119 cir.switch (%arg0 : !s64i) {120 cir.yield121 }122 // CHECK-NOT: llvm.switch123 cir.return124 }125// CHECK: cir.func{{.*}} @shouldDropEmptySwitch(%arg0: !s64i)126// CHECK-NOT: cir.switch.flat127 128 129 cir.func @shouldFlatMultiBlockCase(%arg0: !s32i) {130 %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init] {alignment = 4 : i64}131 cir.store %arg0, %0 : !s32i, !cir.ptr<!s32i>132 cir.scope {133 %1 = cir.load %0 : !cir.ptr<!s32i>, !s32i134 cir.switch (%1 : !s32i) {135 cir.case (equal, [#cir.int<3> : !s32i]) {136 cir.return137 ^bb1: // no predecessors138 cir.break139 }140 cir.yield141 }142 }143 cir.return144 }145 146// CHECK: cir.func{{.*}} @shouldFlatMultiBlockCase(%arg0: !s32i) {147// CHECK: %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init] {alignment = 4 : i64}148// CHECK: cir.store %arg0, %0 : !s32i, !cir.ptr<!s32i>149// CHECK: cir.br ^bb1150// CHECK: ^bb1: // pred: ^bb0151// CHECK: %1 = cir.load %0 : !cir.ptr<!s32i>, !s32i152// CHECK: cir.switch.flat %1 : !s32i, ^bb[[#DEFAULT:]] [153// CHECK: 3: ^bb[[#BB1:]]154// CHECK: ]155// CHECK: ^bb[[#BB1]]:156// CHECK: cir.return157// CHECK: ^bb[[#DEFAULT]]:158// CHECK: cir.br ^bb[[#RET_BB:]]159// CHECK: ^bb[[#RET_BB]]: // pred: ^bb[[#DEFAULT]]160// CHECK: cir.return161// CHECK: }162 163 164 cir.func @shouldFlatNestedBreak(%arg0: !s32i, %arg1: !s32i) -> !s32i {165 %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}166 %1 = cir.alloca !s32i, !cir.ptr<!s32i>, ["y", init] {alignment = 4 : i64}167 %2 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}168 cir.store %arg0, %0 : !s32i, !cir.ptr<!s32i>169 cir.store %arg1, %1 : !s32i, !cir.ptr<!s32i>170 cir.scope {171 %5 = cir.load %0 : !cir.ptr<!s32i>, !s32i172 cir.switch (%5 : !s32i) {173 cir.case (equal, [#cir.int<0> : !s32i]) {174 cir.scope {175 %6 = cir.load %1 : !cir.ptr<!s32i>, !s32i176 %7 = cir.const #cir.int<0> : !s32i177 %8 = cir.cmp(ge, %6, %7) : !s32i, !cir.bool178 cir.if %8 {179 cir.break180 }181 }182 cir.break183 }184 cir.yield185 }186 }187 %3 = cir.const #cir.int<3> : !s32i188 cir.store %3, %2 : !s32i, !cir.ptr<!s32i>189 %4 = cir.load %2 : !cir.ptr<!s32i>, !s32i190 cir.return %4 : !s32i191 }192// CHECK: cir.func{{.*}} @shouldFlatNestedBreak(%arg0: !s32i, %arg1: !s32i) -> !s32i {193// CHECK: cir.switch.flat %[[COND:.*]] : !s32i, ^bb[[#DEFAULT_BB:]] [194// CHECK: 0: ^bb[[#BB1:]]195// CHECK: ]196// CHECK: ^bb[[#BB1]]:197// CHECK: cir.br ^bb[[#COND_BB:]]198// CHECK: ^bb[[#COND_BB]]:199// CHECK: cir.brcond {{%.*}} ^bb[[#TRUE_BB:]], ^bb[[#FALSE_BB:]]200// CHECK: ^bb[[#TRUE_BB]]:201// CHECK: cir.br ^bb[[#DEFAULT_BB]]202// CHECK: ^bb[[#FALSE_BB]]:203// CHECK: cir.br ^bb[[#PRED_BB:]]204// CHECK: ^bb[[#PRED_BB]]:205// CHECK: cir.br ^bb[[#DEFAULT_BB]]206// CHECK: ^bb[[#DEFAULT_BB]]:207// CHECK: cir.br ^bb[[#RET_BB:]]208// CHECK: ^bb[[#RET_BB]]:209// CHECK: cir.return210// CHECK: }211 212 213 cir.func @flatCaseRange(%arg0: !s32i) -> !s32i {214 %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}215 %1 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}216 %2 = cir.alloca !s32i, !cir.ptr<!s32i>, ["y", init] {alignment = 4 : i64}217 cir.store %arg0, %0 : !s32i, !cir.ptr<!s32i>218 %3 = cir.const #cir.int<0> : !s32i219 cir.store %3, %2 : !s32i, !cir.ptr<!s32i>220 cir.scope {221 %6 = cir.load %0 : !cir.ptr<!s32i>, !s32i222 cir.switch (%6 : !s32i) {223 cir.case (equal, [#cir.int<-100> : !s32i]) {224 %7 = cir.const #cir.int<1> : !s32i225 cir.store %7, %2 : !s32i, !cir.ptr<!s32i>226 cir.break227 }228 cir.case (range, [#cir.int<1> : !s32i, #cir.int<100> : !s32i]) {229 %7 = cir.const #cir.int<2> : !s32i230 cir.store %7, %2 : !s32i, !cir.ptr<!s32i>231 cir.break232 }233 cir.case (default, []) {234 %7 = cir.const #cir.int<3> : !s32i235 cir.store %7, %2 : !s32i, !cir.ptr<!s32i>236 cir.break237 }238 cir.yield239 }240 }241 %4 = cir.load %2 : !cir.ptr<!s32i>, !s32i242 cir.store %4, %1 : !s32i, !cir.ptr<!s32i>243 %5 = cir.load %1 : !cir.ptr<!s32i>, !s32i244 cir.return %5 : !s32i245 }246// CHECK: cir.func{{.*}} @flatCaseRange(%arg0: !s32i) -> !s32i {247// CHECK: cir.switch.flat %[[X:[0-9]+]] : !s32i, ^[[JUDGE_RANGE:bb[0-9]+]] [248// CHECK-NEXT: -100: ^[[CASE_EQUAL:bb[0-9]+]]249// CHECK-NEXT: ]250// CHECK-NEXT: ^[[UNRACHABLE_BB:.+]]: // no predecessors251// CHECK-NEXT: cir.br ^[[CASE_EQUAL]]252// CHECK-NEXT: ^[[CASE_EQUAL]]:253// CHECK-NEXT: cir.int<1>254// CHECK-NEXT: cir.store255// CHECK-NEXT: cir.br ^[[EPILOG:bb[0-9]+]]256// CHECK-NEXT: ^[[CASE_RANGE:bb[0-9]+]]:257// CHECK-NEXT: cir.int<2>258// CHECK-NEXT: cir.store259// CHECK-NEXT: cir.br ^[[EPILOG]]260// CHECK-NEXT: ^[[JUDGE_RANGE]]:261// CHECK-NEXT: %[[RANGE:[0-9]+]] = cir.const #cir.int<99>262// CHECK-NEXT: %[[LOWER_BOUND:[0-9]+]] = cir.const #cir.int<1>263// CHECK-NEXT: %[[DIFF:[0-9]+]] = cir.binop(sub, %[[X]], %[[LOWER_BOUND]])264// CHECK-NEXT: %[[U_DIFF:[0-9]+]] = cir.cast integral %[[DIFF]] : !s32i -> !u32i265// CHECK-NEXT: %[[U_RANGE:[0-9]+]] = cir.cast integral %[[RANGE]] : !s32i -> !u32i266// CHECK-NEXT: %[[CMP_RESULT:[0-9]+]] = cir.cmp(le, %[[U_DIFF]], %[[U_RANGE]])267// CHECK-NEXT: cir.brcond %[[CMP_RESULT]] ^[[CASE_RANGE]], ^[[CASE_DEFAULT:bb[0-9]+]]268// CHECK-NEXT: ^[[CASE_DEFAULT]]:269// CHECK-NEXT: cir.int<3>270// CHECK-NEXT: cir.store271// CHECK-NEXT: cir.br ^[[EPILOG]]272// CHECK-NEXT: ^[[EPILOG]]:273// CHECK-NEXT: cir.br ^[[EPILOG_END:bb[0-9]+]]274// CHECK-NEXT: ^[[EPILOG_END]]:275// CHECK: cir.return276// CHECK: }277 278 cir.func @_Z8bigRangei(%arg0: !s32i) {279 %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init] {alignment = 4 : i64}280 cir.store %arg0, %0 : !s32i, !cir.ptr<!s32i>281 cir.scope {282 %1 = cir.load %0 : !cir.ptr<!s32i>, !s32i283 cir.switch (%1 : !s32i) {284 cir.case(range, [#cir.int<3> : !s32i, #cir.int<100> : !s32i]) {285 cir.break286 }287 cir.case(default, []) {288 cir.break289 }290 cir.yield291 }292 }293 cir.return294 }295 296// CHECK: cir.func{{.*}} @_Z8bigRangei(%arg0: !s32i) {297// CHECK: cir.switch.flat %[[COND:.*]] : !s32i, ^bb[[#RANGE_BR:]] [298// CHECK: ]299// CHECK: ^bb[[#NO_PRED_BB:]]: // no predecessors300// CHECK: cir.br ^bb[[#DEFAULT_BB:]]301// CHECK: ^bb[[#DEFAULT_BB]]: // 2 preds: ^bb[[#NO_PRED_BB]], ^bb[[#RANGE_BR]]302// CHECK: cir.br ^bb[[#EXIT:]]303// CHECK: ^bb[[#RANGE_BR]]: // pred: ^bb[[#BB2:]]304// CHECK: %[[CONST97:.*]] = cir.const #cir.int<97> : !s32i305// CHECK: %[[CONST3:.*]] = cir.const #cir.int<3> : !s32i306// CHECK: %[[SUB:.*]] = cir.binop(sub, %[[COND]], %[[CONST3]]) : !s32i307// CHECK: %[[CAST1:.*]] = cir.cast integral %[[SUB]] : !s32i -> !u32i308// CHECK: %[[CAST2:.*]] = cir.cast integral %[[CONST97]] : !s32i -> !u32i309// CHECK: %[[CMP:.*]] = cir.cmp(le, %[[CAST1]], %[[CAST2]]) : !u32i, !cir.bool310// CHECK: cir.brcond %7 ^bb[[#DEFAULT_BB]], ^bb[[#RANGE_BB:]]311// CHECK: ^bb[[#RANGE_BB]]: // pred: ^bb[[#RANGE_BR]]312// CHECK: cir.br ^bb[[#EXIT]]313// CHECK: ^bb[[#EXIT]]: // 2 preds: ^bb[[#DEFAULT_BB]], ^bb[[#RANGE_BB]]314// CHECK: cir.br ^bb[[#RET_BB:]]315// CHECK: ^bb[[#RET_BB]]: // pred: ^bb[[#EXIT]]316// CHECK: cir.return317// CHECK: }318}319