Miscompilation of do-while when the while starts with a branch #2394. Also: change do-while to make the lowering follow the execution.

This commit is contained in:
Christoffer Lerno
2025-08-18 21:04:52 +02:00
parent db45abdfc7
commit eeab73df4e
5 changed files with 254 additions and 171 deletions

View File

@@ -19,20 +19,20 @@ entry:
store i32 0, ptr %a, align 4
br label %loop.body
loop.cond: ; preds = %loop.body
%0 = load i32, ptr %a, align 4
%lt = icmp slt i32 %0, 10
br i1 %lt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond, %entry
%1 = load i32, ptr %a, align 4
%add = add i32 %1, 1
%0 = load i32, ptr %a, align 4
%add = add i32 %0, 1
store i32 %add, ptr %a, align 4
%2 = load i32, ptr %a, align 4
%add1 = add i32 %2, 1
%1 = load i32, ptr %a, align 4
%add1 = add i32 %1, 1
store i32 %add1, ptr %a, align 4
br label %loop.cond
loop.cond: ; preds = %loop.body
%2 = load i32, ptr %a, align 4
%lt = icmp slt i32 %2, 10
br i1 %lt, label %loop.body, label %loop.exit
loop.exit: ; preds = %loop.cond
ret void
}

View File

@@ -0,0 +1,95 @@
module test;
import std;
fn int main()
{
int i = 10;
do
{
io::printfn("%s", i);
} while (@my_ok(nonzero(--i)));
return 0;
}
macro @my_ok(#z)
{
if (catch #z) return false;
return true;
}
faultdef WAS_ZERO;
fn int? nonzero(int x)
{
if (x == 0) return WAS_ZERO?;
return x;
}
/* #expect: test.ll
define i32 @main() #0 {
entry:
%i = alloca i32, align 4
%varargslots = alloca [1 x %any], align 8
%retparam = alloca i64, align 8
%taddr = alloca %"char[]", align 8
%taddr1 = alloca %"any[]", align 8
%blockret = alloca i8, align 1
%temp_err = alloca i64, align 8
%retparam2 = alloca i32, align 4
store i32 10, ptr %i, align 4
br label %loop.body
loop.body: ; preds = %expr_block.exit, %entry
%0 = insertvalue %any undef, ptr %i, 0
%1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.int" to i64), 1
store %any %1, ptr %varargslots, align 8
%2 = insertvalue %"any[]" undef, ptr %varargslots, 0
%"$$temp" = insertvalue %"any[]" %2, i64 1, 1
store %"char[]" { ptr @.str, i64 2 }, ptr %taddr, align 8
%3 = load [2 x i64], ptr %taddr, align 8
store %"any[]" %"$$temp", ptr %taddr1, align 8
%4 = load [2 x i64], ptr %taddr1, align 8
%5 = call i64 @std.io.printfn(ptr %retparam, [2 x i64] %3, [2 x i64] %4)
br label %loop.cond
loop.cond: ; preds = %loop.body
br label %testblock
testblock: ; preds = %loop.cond
%6 = load i32, ptr %i, align 4
%sub = sub i32 %6, 1
store i32 %sub, ptr %i, align 4
%7 = call i64 @test.nonzero(ptr %retparam2, i32 %sub)
%not_err = icmp eq i64 %7, 0
%8 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
br i1 %8, label %after_check, label %assign_optional
assign_optional: ; preds = %testblock
store i64 %7, ptr %temp_err, align 8
br label %end_block
after_check: ; preds = %testblock
store i64 0, ptr %temp_err, align 8
br label %end_block
end_block: ; preds = %after_check, %assign_optional
%9 = load i64, ptr %temp_err, align 8
%i2b = icmp ne i64 %9, 0
br i1 %i2b, label %if.then, label %if.exit
if.then: ; preds = %end_block
store i8 0, ptr %blockret, align 1
br label %expr_block.exit
if.exit: ; preds = %end_block
store i8 1, ptr %blockret, align 1
br label %expr_block.exit
expr_block.exit: ; preds = %if.exit, %if.then
%10 = load i8, ptr %blockret, align 1
%11 = trunc i8 %10 to i1
br i1 %11, label %loop.body, label %loop.exit
loop.exit: ; preds = %expr_block.exit
ret i32 0
}

View File

@@ -54,19 +54,12 @@ entry:
store i32 10, ptr %i, align 4
br label %loop.body
loop.cond: ; preds = %if.exit
%0 = load i32, ptr %i, align 4
%sub = sub i32 %0, 1
store i32 %sub, ptr %i, align 4
%gt = icmp sgt i32 %0, 0
br i1 %gt, label %loop.body, label %loop.exit
loop.body: ; preds = %loop.cond, %entry
%1 = call i32 @foo.test()
call void (ptr, ...) @printf(ptr @.str, i32 %1)
%2 = load i32, ptr %i, align 4
%gt1 = icmp sgt i32 %2, 100
br i1 %gt1, label %if.then, label %if.exit
%0 = call i32 @foo.test()
call void (ptr, ...) @printf(ptr @.str, i32 %0)
%1 = load i32, ptr %i, align 4
%gt = icmp sgt i32 %1, 100
br i1 %gt, label %if.then, label %if.exit
if.then: ; preds = %loop.body
br label %loop.exit
@@ -74,33 +67,40 @@ if.then: ; preds = %loop.body
if.exit: ; preds = %loop.body
br label %loop.cond
loop.exit: ; preds = %if.then, %loop.cond
loop.cond: ; preds = %if.exit
%2 = load i32, ptr %i, align 4
%sub = sub i32 %2, 1
store i32 %sub, ptr %i, align 4
%gt1 = icmp sgt i32 %2, 0
br i1 %gt1, label %loop.body, label %loop.exit
loop.exit: ; preds = %loop.cond, %if.then
store i32 1, ptr %i, align 4
br label %loop.body3
br label %loop.body2
loop.cond2: ; preds = %if.exit5
%3 = load i32, ptr %i, align 4
%add = add i32 %3, 1
store i32 %add, ptr %i, align 4
%lt = icmp slt i32 %3, 100
br i1 %lt, label %loop.body3, label %loop.exit6
loop.body3: ; preds = %loop.cond2, %loop.exit
%4 = call i32 @foo.test()
loop.body2: ; preds = %loop.cond5, %loop.exit
%3 = call i32 @foo.test()
%4 = load i32, ptr %i, align 4
call void (ptr, ...) @printf(ptr @.str.1, i32 %4, i32 %3)
%5 = load i32, ptr %i, align 4
call void (ptr, ...) @printf(ptr @.str.1, i32 %5, i32 %4)
%6 = load i32, ptr %i, align 4
%smod = srem i32 %6, 3
%smod = srem i32 %5, 3
%eq = icmp eq i32 %smod, 0
br i1 %eq, label %if.then4, label %if.exit5
br i1 %eq, label %if.then3, label %if.exit4
if.then4: ; preds = %loop.body3
if.then3: ; preds = %loop.body2
br label %loop.exit6
if.exit5: ; preds = %loop.body3
br label %loop.cond2
if.exit4: ; preds = %loop.body2
br label %loop.cond5
loop.exit6: ; preds = %if.then4, %loop.cond2
loop.cond5: ; preds = %if.exit4
%6 = load i32, ptr %i, align 4
%add = add i32 %6, 1
store i32 %add, ptr %i, align 4
%lt = icmp slt i32 %6, 100
br i1 %lt, label %loop.body2, label %loop.exit6
loop.exit6: ; preds = %loop.cond5, %if.then3
ret void
}