Skip to content

Commit 2de08b9

Browse files
wenpenlanza
authored andcommitted
[CIR][CIRGen] Add support for gnu range on switch stmts (#599)
Fix #596
1 parent 2b0710e commit 2de08b9

File tree

2 files changed

+217
-5
lines changed

2 files changed

+217
-5
lines changed

clang/lib/CIR/CodeGen/CIRGenStmt.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -615,11 +615,21 @@ CIRGenFunction::foldCaseStmt(const clang::CaseStmt &S, mlir::Type condType,
615615
// Fold cascading cases whenever possible to simplify codegen a bit.
616616
while (caseStmt) {
617617
lastCase = caseStmt;
618-
auto intVal = caseStmt->getLHS()->EvaluateKnownConstInt(getContext());
619-
caseEltValueListAttr.push_back(mlir::cir::IntAttr::get(condType, intVal));
618+
619+
auto startVal = caseStmt->getLHS()->EvaluateKnownConstInt(getContext());
620+
auto endVal = startVal;
621+
if (auto *rhs = caseStmt->getRHS()) {
622+
endVal = rhs->EvaluateKnownConstInt(getContext());
623+
}
624+
for (auto intVal = startVal; intVal <= endVal; ++intVal) {
625+
caseEltValueListAttr.push_back(mlir::cir::IntAttr::get(condType, intVal));
626+
}
627+
620628
caseStmt = dyn_cast_or_null<CaseStmt>(caseStmt->getSubStmt());
621629
}
622630

631+
assert(!caseEltValueListAttr.empty() && "empty case value NYI");
632+
623633
auto *ctxt = builder.getContext();
624634

625635
auto caseAttr = mlir::cir::CaseAttr::get(
@@ -668,9 +678,6 @@ mlir::LogicalResult CIRGenFunction::buildCaseDefaultCascade(
668678
mlir::LogicalResult
669679
CIRGenFunction::buildCaseStmt(const CaseStmt &S, mlir::Type condType,
670680
SmallVector<mlir::Attribute, 4> &caseAttrs) {
671-
assert((!S.getRHS() || !S.caseStmtIsGNURange()) &&
672-
"case ranges not implemented");
673-
674681
auto *caseStmt = foldCaseStmt(S, condType, caseAttrs);
675682
return buildCaseDefaultCascade(caseStmt, condType, caseAttrs);
676683
}
+205
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
3+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll
4+
// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
5+
6+
enum letter {
7+
A, B, C, D, E, F, G, H, I, J, L
8+
};
9+
10+
int sw1(enum letter c) {
11+
switch (c) {
12+
case A ... C:
13+
case D:
14+
case E ... F:
15+
case G ... L:
16+
return 1;
17+
default:
18+
return 0;
19+
}
20+
}
21+
22+
// CIR: cir.func @_Z3sw16letter
23+
// CIR: cir.scope {
24+
// CIR: cir.switch
25+
// CIR-NEXT: case (anyof, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] : !s32i) {
26+
// CIR: cir.return
27+
// CIR-NEXT: },
28+
// CIR-NEXT: case (default) {
29+
// CIR: cir.return
30+
// CIR-NEXT: }
31+
// CIR-NEXT: ]
32+
// CIR-NEXT: }
33+
34+
// LLVM: @_Z3sw16letter
35+
// LLVM: switch i32 %[[C:[0-9]+]], label %[[DEFAULT:[0-9]+]] [
36+
// LLVM-NEXT: i32 0, label %[[CASE:[0-9]+]]
37+
// LLVM-NEXT: i32 1, label %[[CASE]]
38+
// LLVM-NEXT: i32 2, label %[[CASE]]
39+
// LLVM-NEXT: i32 3, label %[[CASE]]
40+
// LLVM-NEXT: i32 4, label %[[CASE]]
41+
// LLVM-NEXT: i32 5, label %[[CASE]]
42+
// LLVM-NEXT: i32 6, label %[[CASE]]
43+
// LLVM-NEXT: i32 7, label %[[CASE]]
44+
// LLVM-NEXT: i32 8, label %[[CASE]]
45+
// LLVM-NEXT: i32 9, label %[[CASE]]
46+
// LLVM-NEXT: i32 10, label %[[CASE]]
47+
// LLVM-NEXT: ]
48+
// LLVM: [[CASE]]:
49+
// LLVM: store i32 1
50+
// LLVM: ret
51+
// LLVM: [[DEFAULT]]:
52+
// LLVM: store i32 0
53+
// LLVM: ret
54+
55+
56+
int sw2(enum letter c) {
57+
switch (c) {
58+
case A ... C:
59+
case L ... A:
60+
return 1;
61+
default:
62+
return 0;
63+
}
64+
}
65+
66+
// CIR: cir.func @_Z3sw26letter
67+
// CIR: cir.scope {
68+
// CIR: cir.switch
69+
// CIR-NEXT: case (anyof, [0, 1, 2] : !s32i) {
70+
// CIR: cir.return
71+
// CIR-NEXT: },
72+
// CIR-NEXT: case (default) {
73+
// CIR: cir.return
74+
// CIR-NEXT: }
75+
// CIR-NEXT: ]
76+
// CIR-NEXT: }
77+
78+
// LLVM: @_Z3sw26letter
79+
// LLVM: switch i32 %[[C:[0-9]+]], label %[[DEFAULT:[0-9]+]] [
80+
// LLVM-NEXT: i32 0, label %[[CASE:[0-9]+]]
81+
// LLVM-NEXT: i32 1, label %[[CASE]]
82+
// LLVM-NEXT: i32 2, label %[[CASE]]
83+
// LLVM-NEXT: ]
84+
// LLVM: [[CASE]]:
85+
// LLVM: store i32 1
86+
// LLVM: ret
87+
// LLVM: [[DEFAULT]]:
88+
// LLVM: store i32 0
89+
// LLVM: ret
90+
91+
void sw3(enum letter c) {
92+
int x = 0;
93+
switch (c) {
94+
case A ... C:
95+
x = 1;
96+
break;
97+
case D ... F:
98+
x = 2;
99+
break;
100+
case G ... I:
101+
x = 3;
102+
break;
103+
case J ... L:
104+
x = 4;
105+
break;
106+
}
107+
}
108+
109+
// CIR: cir.func @_Z3sw36letter
110+
// CIR: cir.scope {
111+
// CIR: cir.switch
112+
// CIR-NEXT: case (anyof, [0, 1, 2] : !s32i) {
113+
// CIR-NEXT: cir.int<1>
114+
// CIR: cir.break
115+
// CIR-NEXT: },
116+
// CIR-NEXT: case (anyof, [3, 4, 5] : !s32i) {
117+
// CIR-NEXT: cir.int<2>
118+
// CIR: cir.break
119+
// CIR-NEXT: },
120+
// CIR-NEXT: case (anyof, [6, 7, 8] : !s32i) {
121+
// CIR-NEXT: cir.int<3>
122+
// CIR: cir.break
123+
// CIR-NEXT: },
124+
// CIR-NEXT: case (anyof, [9, 10] : !s32i) {
125+
// CIR-NEXT: cir.int<4>
126+
// CIR: cir.break
127+
// CIR-NEXT: }
128+
// CIR-NEXT: ]
129+
// CIR-NEXT: }
130+
131+
// LLVM: @_Z3sw36letter
132+
// LLVM: switch i32 %[[C:[0-9]+]], label %[[DEFAULT:[0-9]+]] [
133+
// LLVM-NEXT: i32 0, label %[[CASE_AC:[0-9]+]]
134+
// LLVM-NEXT: i32 1, label %[[CASE_AC]]
135+
// LLVM-NEXT: i32 2, label %[[CASE_AC]]
136+
// LLVM-NEXT: i32 3, label %[[CASE_DF:[0-9]+]]
137+
// LLVM-NEXT: i32 4, label %[[CASE_DF]]
138+
// LLVM-NEXT: i32 5, label %[[CASE_DF]]
139+
// LLVM-NEXT: i32 6, label %[[CASE_GI:[0-9]+]]
140+
// LLVM-NEXT: i32 7, label %[[CASE_GI]]
141+
// LLVM-NEXT: i32 8, label %[[CASE_GI]]
142+
// LLVM-NEXT: i32 9, label %[[CASE_JL:[0-9]+]]
143+
// LLVM-NEXT: i32 10, label %[[CASE_JL]]
144+
// LLVM-NEXT: ]
145+
// LLVM: [[CASE_AC]]:
146+
// LLVM: store i32 1, ptr %[[X:[0-9]+]]
147+
// LLVM: br label %[[EPILOG:[0-9]+]]
148+
// LLVM: [[CASE_DF]]:
149+
// LLVM: store i32 2, ptr %[[X]]
150+
// LLVM: br label %[[EPILOG]]
151+
// LLVM: [[CASE_GI]]:
152+
// LLVM: store i32 3, ptr %[[X]]
153+
// LLVM: br label %[[EPILOG]]
154+
// LLVM: [[CASE_JL]]:
155+
// LLVM: store i32 4, ptr %[[X]]
156+
// LLVM: br label %[[EPILOG]]
157+
// LLVM: [[EPILOG]]:
158+
// LLVM: ret void
159+
160+
void sw4(int x) {
161+
switch (x) {
162+
case 66 ... 233:
163+
break;
164+
case -50 ... 50:
165+
break;
166+
}
167+
}
168+
169+
// CIR: cir.func @_Z3sw4i
170+
// CIR: cir.scope {
171+
// CIR: cir.switch
172+
// CIR-NEXT: case (anyof, [66, 67, 68, 69, {{[0-9, ]+}}, 230, 231, 232, 233] : !s32i) {
173+
// CIR-NEXT: cir.break
174+
// CIR-NEXT: },
175+
// CIR-NEXT: case (anyof, [-50, -49, -48, -47, {{[0-9, -]+}}, -1, 0, 1, {{[0-9, ]+}}, 47, 48, 49, 50] : !s32i) {
176+
// CIR-NEXT: cir.break
177+
// CIR-NEXT: }
178+
// CIR-NEXT: ]
179+
// CIR-NEXT: }
180+
181+
// LLVM: @_Z3sw4i
182+
// LLVM: switch i32 %[[X:[0-9]+]], label %[[DEFAULT:[0-9]+]] [
183+
// LLVM-NEXT: i32 66, label %[[CASE_66_233:[0-9]+]]
184+
// LLVM-NEXT: i32 67, label %[[CASE_66_233]]
185+
// ...
186+
// LLVM: i32 232, label %[[CASE_66_233]]
187+
// LLVM-NEXT: i32 233, label %[[CASE_66_233]]
188+
// LLVM-NEXT: i32 -50, label %[[CASE_NEG50_50:[0-9]+]]
189+
// LLVM-NEXT: i32 -49, label %[[CASE_NEG50_50]]
190+
// ...
191+
// LLVM: i32 -1, label %[[CASE_NEG50_50]]
192+
// LLVM-NEXT: i32 0, label %[[CASE_NEG50_50]]
193+
// LLVM-NEXT: i32 1, label %[[CASE_NEG50_50]]
194+
// ...
195+
// LLVM: i32 49, label %[[CASE_NEG50_50]]
196+
// LLVM-NEXT: i32 50, label %[[CASE_NEG50_50]]
197+
// LLVM-NEXT: ]
198+
// LLVM: [[CASE_66_233]]:
199+
// LLVM: br label %[[EPILOG:[0-9]+]]
200+
// LLVM: [[CASE_NEG50_50]]:
201+
// LLVM: br label %[[EPILOG]]
202+
// LLVM: [[EPILOG]]:
203+
// LLVM: ret void
204+
205+

0 commit comments

Comments
 (0)