Skip to content

Commit 59d969c

Browse files
authored
[CIR][CIRGen] Create a new block after break and continue (#611)
Without this patch, CIR CodeGen continue to generate in the same block after `cir.break` and `cir.continue`, which would cause verification error because `cir.break` and `cir.continue` should appear at the end of blocks. This patch creates a new dangling block after generating `cir.break` and `cir.continue` to fix the issue. This will fix #323.
1 parent 7501afa commit 59d969c

File tree

6 files changed

+123
-31
lines changed

6 files changed

+123
-31
lines changed

clang/lib/CIR/CodeGen/CIRGenStmt.cpp

+10-11
Original file line numberDiff line numberDiff line change
@@ -551,20 +551,11 @@ mlir::LogicalResult CIRGenFunction::buildGotoStmt(const GotoStmt &S) {
551551
// info support just yet, look at this again once we have it.
552552
assert(builder.getInsertionBlock() && "not yet implemented");
553553

554-
mlir::Block *currBlock = builder.getBlock();
555-
mlir::Block *gotoBlock = currBlock;
556-
if (!currBlock->empty() &&
557-
currBlock->back().hasTrait<mlir::OpTrait::IsTerminator>()) {
558-
gotoBlock = builder.createBlock(builder.getBlock()->getParent());
559-
builder.setInsertionPointToEnd(gotoBlock);
560-
}
561-
562-
// A goto marks the end of a block, create a new one for codegen after
563-
// buildGotoStmt can resume building in that block.
564-
565554
builder.create<mlir::cir::GotoOp>(getLoc(S.getSourceRange()),
566555
S.getLabel()->getName());
567556

557+
// A goto marks the end of a block, create a new one for codegen after
558+
// buildGotoStmt can resume building in that block.
568559
// Insert the new block to continue codegen after goto.
569560
builder.createBlock(builder.getBlock()->getParent());
570561

@@ -597,11 +588,19 @@ mlir::LogicalResult CIRGenFunction::buildLabel(const LabelDecl *D) {
597588
mlir::LogicalResult
598589
CIRGenFunction::buildContinueStmt(const clang::ContinueStmt &S) {
599590
builder.createContinue(getLoc(S.getContinueLoc()));
591+
592+
// Insert the new block to continue codegen after the continue statement.
593+
builder.createBlock(builder.getBlock()->getParent());
594+
600595
return mlir::success();
601596
}
602597

603598
mlir::LogicalResult CIRGenFunction::buildBreakStmt(const clang::BreakStmt &S) {
604599
builder.createBreak(getLoc(S.getBreakLoc()));
600+
601+
// Insert the new block to continue codegen after the break statement.
602+
builder.createBlock(builder.getBlock()->getParent());
603+
605604
return mlir::success();
606605
}
607606

clang/test/CIR/CodeGen/goto.cpp

-20
Original file line numberDiff line numberDiff line change
@@ -101,26 +101,6 @@ int shouldGenBranch(int x) {
101101
// NOFLAT: ^bb1:
102102
// NOFLAT: cir.label "err"
103103

104-
int shouldCreateBlkForGoto(int a) {
105-
switch (a) {
106-
case(42):
107-
break;
108-
goto exit;
109-
default:
110-
return 0;
111-
};
112-
113-
exit:
114-
return -1;
115-
116-
}
117-
// NOFLAT: cir.func @_Z22shouldCreateBlkForGotoi
118-
// NOFLAT: case (equal, 42) {
119-
// NOFLAT: cir.break
120-
// NOFLAT: ^bb1: // no predecessors
121-
// NOFLAT: cir.goto "exit"
122-
// NOFLAT: }
123-
124104
void severalLabelsInARow(int a) {
125105
int b = a;
126106
goto end1;

clang/test/CIR/CodeGen/loop.cpp

+52
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,55 @@ void l6() {
205205
// CHECK-NEXT: }
206206
// CHECK-NEXT: cir.return
207207
// CHECK-NEXT: }
208+
209+
void unreachable_after_break() {
210+
for (;;) {
211+
break;
212+
int x = 1;
213+
}
214+
}
215+
216+
// CHECK-NEXT: cir.func @_Z23unreachable_after_breakv()
217+
// CHECK-NEXT: cir.scope {
218+
// CHECK-NEXT: %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
219+
// CHECK-NEXT: cir.for : cond {
220+
// CHECK-NEXT: %1 = cir.const #true
221+
// CHECK-NEXT: cir.condition(%1)
222+
// CHECK-NEXT: } body {
223+
// CHECK-NEXT: cir.break
224+
// CHECK-NEXT: ^bb1: // no predecessors
225+
// CHECK-NEXT: %1 = cir.const #cir.int<1> : !s32i
226+
// CHECK-NEXT: cir.store %1, %0 : !s32i, !cir.ptr<!s32i>
227+
// CHECK-NEXT: cir.yield
228+
// CHECK-NEXT: } step {
229+
// CHECK-NEXT: cir.yield
230+
// CHECK-NEXT: }
231+
// CHECK-NEXT: }
232+
// CHECK-NEXT: cir.return
233+
// CHECK-NEXT: }
234+
235+
void unreachable_after_continue() {
236+
for (;;) {
237+
continue;
238+
int x = 1;
239+
}
240+
}
241+
242+
// CHECK-NEXT: cir.func @_Z26unreachable_after_continuev()
243+
// CHECK-NEXT: cir.scope {
244+
// CHECK-NEXT: %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
245+
// CHECK-NEXT: cir.for : cond {
246+
// CHECK-NEXT: %1 = cir.const #true
247+
// CHECK-NEXT: cir.condition(%1)
248+
// CHECK-NEXT: } body {
249+
// CHECK-NEXT: cir.continue
250+
// CHECK-NEXT: ^bb1: // no predecessors
251+
// CHECK-NEXT: %1 = cir.const #cir.int<1> : !s32i
252+
// CHECK-NEXT: cir.store %1, %0 : !s32i, !cir.ptr<!s32i>
253+
// CHECK-NEXT: cir.yield
254+
// CHECK-NEXT: } step {
255+
// CHECK-NEXT: cir.yield
256+
// CHECK-NEXT: }
257+
// CHECK-NEXT: }
258+
// CHECK-NEXT: cir.return
259+
// CHECK-NEXT: }

clang/test/CIR/CodeGen/return.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,22 @@ int &ret0(int &x) {
1212
// CHECK: cir.store %2, %1 : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
1313
// CHECK: %3 = cir.load %1 : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
1414
// CHECK: cir.return %3 : !cir.ptr<!s32i>
15+
16+
int unreachable_after_return() {
17+
return 0;
18+
return 1;
19+
}
20+
21+
// CHECK: cir.func @_Z24unreachable_after_returnv
22+
// CHECK-NEXT: %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
23+
// CHECK-NEXT: %1 = cir.const #cir.int<0> : !s32i
24+
// CHECK-NEXT: cir.store %1, %0 : !s32i, !cir.ptr<!s32i>
25+
// CHECK-NEXT: cir.br ^bb1
26+
// CHECK-NEXT: ^bb1: // 2 preds: ^bb0, ^bb2
27+
// CHECK-NEXT: %2 = cir.load %0 : !cir.ptr<!s32i>, !s32i
28+
// CHECK-NEXT: cir.return %2 : !s32i
29+
// CHECK-NEXT: ^bb2: // no predecessors
30+
// CHECK-NEXT: %3 = cir.const #cir.int<1> : !s32i
31+
// CHECK-NEXT: cir.store %3, %0 : !s32i, !cir.ptr<!s32i>
32+
// CHECK-NEXT: cir.br ^bb1
33+
// CHECK-NEXT: }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s
3+
// XFAIL: *
4+
5+
void unreachable_after_break(int a) {
6+
switch(a) {
7+
case 0:
8+
break;
9+
break;
10+
int x = 1;
11+
}
12+
}
13+
14+
int unreachable_after_return(int a) {
15+
switch (a) {
16+
case 0:
17+
return 0;
18+
return 1;
19+
int x = 1;
20+
}
21+
return 2;
22+
}

clang/test/CIR/CodeGen/switch.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -327,3 +327,23 @@ void fallthrough(int x) {
327327
// CHECK-NEXT: }
328328
// CHECK-NEXT: ]
329329
// CHECK-NEXT: }
330+
331+
int unreachable_after_break_1(int a) {
332+
switch (a) {
333+
case(42):
334+
break;
335+
goto exit;
336+
default:
337+
return 0;
338+
};
339+
340+
exit:
341+
return -1;
342+
343+
}
344+
// CHECK: cir.func @_Z25unreachable_after_break_1i
345+
// CHECK: case (equal, 42) {
346+
// CHECK: cir.break
347+
// CHECK: ^bb1: // no predecessors
348+
// CHECK: cir.goto "exit"
349+
// CHECK: }

0 commit comments

Comments
 (0)