Skip to content

Commit 5675572

Browse files
committed
[CIR][CIRGen] Create a new block after break and continue
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.
1 parent 43094d7 commit 5675572

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)