Skip to content

Commit f7d2b5c

Browse files
isuckatcsBertalanD
andcommitted
[Codegen] do not emit duplicate br instructions
Co-authored-by: Daniel Bertalan <[email protected]>
1 parent 4cefbb1 commit f7d2b5c

13 files changed

+42
-34
lines changed

include/codegen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class Codegen {
5050
llvm::Value *storeValue(llvm::Value *val, llvm::Value *ptr, const Type &type);
5151
llvm::Value *doubleToBool(llvm::Value *v);
5252
llvm::Value *boolToDouble(llvm::Value *v);
53+
void breakIntoBB(llvm::BasicBlock *targetBB);
5354

5455
llvm::Function *getCurrentFunction();
5556
llvm::AllocaInst *allocateStackVariable(const std::string_view identifier,

src/codegen.cpp

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,13 @@ llvm::Value *Codegen::generateIfStmt(const ResolvedIfStmt &stmt) {
6262
trueBB->insertInto(function);
6363
builder.SetInsertPoint(trueBB);
6464
generateBlock(*stmt.trueBlock);
65-
builder.CreateBr(exitBB);
65+
breakIntoBB(exitBB);
6666

6767
if (stmt.falseBlock) {
6868
elseBB->insertInto(function);
69-
7069
builder.SetInsertPoint(elseBB);
7170
generateBlock(*stmt.falseBlock);
72-
builder.CreateBr(exitBB);
71+
breakIntoBB(exitBB);
7372
}
7473

7574
exitBB->insertInto(function);
@@ -92,7 +91,7 @@ llvm::Value *Codegen::generateWhileStmt(const ResolvedWhileStmt &stmt) {
9291

9392
builder.SetInsertPoint(body);
9493
generateBlock(*stmt.body);
95-
builder.CreateBr(header);
94+
breakIntoBB(header);
9695

9796
builder.SetInsertPoint(exit);
9897
return nullptr;
@@ -120,7 +119,8 @@ llvm::Value *Codegen::generateReturnStmt(const ResolvedReturnStmt &stmt) {
120119
storeValue(generateExpr(*stmt.expr), retVal, stmt.expr->type);
121120

122121
assert(retBB && "function with return stmt doesn't have a return block");
123-
return builder.CreateBr(retBB);
122+
breakIntoBB(retBB);
123+
return nullptr;
124124
}
125125

126126
llvm::Value *Codegen::generateMemberExpr(const ResolvedMemberExpr &memberExpr,
@@ -290,6 +290,9 @@ Codegen::generateBinaryOperator(const ResolvedBinaryOperator &binop) {
290290

291291
builder.SetInsertPoint(rhsBB);
292292
llvm::Value *rhs = doubleToBool(generateExpr(*binop.rhs));
293+
294+
assert(!builder.GetInsertBlock()->getTerminator() &&
295+
"a binop terminated the current block");
293296
builder.CreateBr(mergeBB);
294297

295298
rhsBB = builder.GetInsertBlock();
@@ -362,6 +365,15 @@ llvm::Value *Codegen::boolToDouble(llvm::Value *v) {
362365
return builder.CreateUIToFP(v, builder.getDoubleTy(), "to.double");
363366
}
364367

368+
void Codegen::breakIntoBB(llvm::BasicBlock *targetBB) {
369+
llvm::BasicBlock *currentBB = builder.GetInsertBlock();
370+
371+
if (currentBB && !currentBB->getTerminator())
372+
builder.CreateBr(targetBB);
373+
374+
builder.ClearInsertionPoint();
375+
}
376+
365377
llvm::Function *Codegen::getCurrentFunction() {
366378
return builder.GetInsertBlock()->getParent();
367379
};
@@ -405,15 +417,10 @@ void Codegen::generateBlock(const ResolvedBlock &block) {
405417
for (auto &&stmt : block.statements) {
406418
generateStmt(*stmt);
407419

408-
// After a return statement we clear the insertion point, so that
409-
// no other instructions are inserted into the current block and break.
410-
// The break ensures that no other instruction is generated that will be
411-
// inserted regardless of there is no insertion point and crash (e.g.:
412-
// CreateStore, CreateLoad).
413-
if (dynamic_cast<const ResolvedReturnStmt *>(stmt.get())) {
414-
builder.ClearInsertionPoint();
420+
// We exited the current basic block for some reason, so there is
421+
// no need for generating the remaining instructions.
422+
if (!builder.GetInsertBlock())
415423
break;
416-
}
417424
}
418425
}
419426

@@ -460,7 +467,7 @@ void Codegen::generateFunctionBody(const ResolvedFunctionDecl &functionDecl) {
460467
generateBlock(*functionDecl.body);
461468

462469
if (retBB->hasNPredecessorsOrMore(1)) {
463-
builder.CreateBr(retBB);
470+
breakIntoBB(retBB);
464471
retBB->insertInto(function);
465472
builder.SetInsertPoint(retBB);
466473
}

test/codegen/condition_empty_merge.yl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn main(): void {
2222
// CHECK-NEXT: if.true: ; preds = %entry
2323
// CHECK-NEXT: br label %return
2424
// CHECK-NEXT:
25-
// CHECK-NEXT: if.exit: ; preds = <null operand!>, %entry
25+
// CHECK-NEXT: if.exit: ; preds = %entry
2626
// CHECK-NEXT: br label %return
2727
// CHECK-NEXT:
2828
// CHECK-NEXT: return: ; preds = %if.exit, %if.true

test/codegen/constexpr.yl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fn constant(): number {
1414
// CHECK-NEXT: store double 1.000000e+00, double* %retval, align 8
1515
// CHECK-NEXT: br label %return
1616
// CHECK-NEXT:
17-
// CHECK-NEXT: return: ; preds = <null operand!>, %entry
17+
// CHECK-NEXT: return: ; preds = %entry
1818
// CHECK-NEXT: %0 = load double, double* %retval, align 8
1919
// CHECK-NEXT: ret double %0
2020
// CHECK-NEXT: }
@@ -28,7 +28,7 @@ fn constant2(): number {
2828
// CHECK-NEXT: store double 0.000000e+00, double* %retval, align 8
2929
// CHECK-NEXT: br label %return
3030
// CHECK-NEXT:
31-
// CHECK-NEXT: return: ; preds = <null operand!>, %entry
31+
// CHECK-NEXT: return: ; preds = %entry
3232
// CHECK-NEXT: %0 = load double, double* %retval, align 8
3333
// CHECK-NEXT: ret double %0
3434
// CHECK-NEXT: }

test/codegen/exercise/immutable_parameters.yl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ fn foo(s: S, y: number): number {
1818
// CHECK-NEXT: store double %3, double* %retval, align 8
1919
// CHECK-NEXT: br label %return
2020
// CHECK-NEXT:
21-
// CHECK-NEXT: return: ; preds = <null operand!>, %entry
21+
// CHECK-NEXT: return: ; preds = %entry
2222
// CHECK-NEXT: %4 = load double, double* %retval, align 8
2323
// CHECK-NEXT: ret double %4
2424
// CHECK-NEXT: }

test/codegen/exercise/return_struct.yl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ fn foo(var x: number): Small {
4444
// CHECK-NEXT: br label %return
4545

4646
// CHECK-NEXT:
47-
// CHECK-NEXT: return: ; preds = <null operand!>, %entry
47+
// CHECK-NEXT: return: ; preds = %entry
4848
// CHECK-NEXT: ret void
4949
// CHECK-NEXT: }
5050

@@ -74,7 +74,7 @@ fn bar(): S {
7474

7575
// CHECK-NEXT: br label %return
7676
// CHECK-NEXT:
77-
// CHECK-NEXT: return: ; preds = <null operand!>, %entry
77+
// CHECK-NEXT: return: ; preds = %entry
7878
// CHECK-NEXT: ret void
7979
// CHECK-NEXT: }
8080

test/codegen/exercise/struct_parameter.yl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn bar(var s: S): S {
3030
// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %0, i8* align 8 %1, i64 16, i1 false)
3131
// CHECK-NEXT: br label %return
3232
// CHECK-NEXT:
33-
// CHECK-NEXT: return: ; preds = <null operand!>, %entry
33+
// CHECK-NEXT: return: ; preds = %entry
3434
// CHECK-NEXT: ret void
3535
// CHECK-NEXT: }
3636

test/codegen/exercise/structs_generated_first.yl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ fn foo(s: S): S2 {
2525

2626
// CHECK-NEXT: br label %return
2727
// CHECK-NEXT:
28-
// CHECK-NEXT: return: ; preds = <null operand!>, %entry
28+
// CHECK-NEXT: return: ; preds = %entry
2929
// CHECK-NEXT: ret void
3030
// CHECK-NEXT: }
3131

test/codegen/multiple_return.yl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ fn main(): void {
1010
// CHECK-NEXT: entry:
1111
// CHECK-NEXT: br label %return
1212
// CHECK-NEXT:
13-
// CHECK-NEXT: return: ; preds = <null operand!>, %entry
13+
// CHECK-NEXT: return: ; preds = %entry
1414
// CHECK-NEXT: ret void
1515
// CHECK-NEXT: }

test/codegen/multiple_return_if.yl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@ fn foo(var x: number): number {
3939
// CHECK-NEXT: store double 1.000000e+01, double* %retval, align 8
4040
// CHECK-NEXT: br label %return
4141
// CHECK-NEXT:
42-
// CHECK-NEXT: if.exit: ; preds = <null operand!>, %if.false
42+
// CHECK-NEXT: if.exit: ; preds = %if.false
4343
// CHECK-NEXT: br label %if.exit5
4444
// CHECK-NEXT:
45-
// CHECK-NEXT: if.exit5: ; preds = %if.exit, <null operand!>
45+
// CHECK-NEXT: if.exit5: ; preds = %if.exit
4646
// CHECK-NEXT: store double 5.200000e+00, double* %retval, align 8
4747
// CHECK-NEXT: br label %return
4848
// CHECK-NEXT:
49-
// CHECK-NEXT: return: ; preds = <null operand!>, %if.exit5, %if.true4, %if.true
49+
// CHECK-NEXT: return: ; preds = %if.exit5, %if.true4, %if.true
5050
// CHECK-NEXT: %4 = load double, double* %retval, align 8
5151
// CHECK-NEXT: ret double %4
5252
// CHECK-NEXT: }

0 commit comments

Comments
 (0)