From ef9d88f3ff08bff4e431791d987dc8af32d7e62c Mon Sep 17 00:00:00 2001 From: Philipp Grulich Date: Fri, 20 Dec 2024 22:23:33 +0100 Subject: [PATCH] add new execution tests that cover loops with breaks (#72) --- nautilus/test/benchmark/TracingBenchmark.cpp | 1 + nautilus/test/common/LoopFunctions.hpp | 35 +++++++++++++++++++ .../data/loop-tests/after_ssa/forBreak.trace | 24 +++++++++++++ .../loop-tests/after_ssa/whileBreak.trace | 21 +++++++++++ .../loop-tests/after_ssa/whileContinue.trace | 25 +++++++++++++ .../test/data/loop-tests/ir/forBreak.trace | 34 ++++++++++++++++++ .../test/data/loop-tests/ir/whileBreak.trace | 31 ++++++++++++++++ .../data/loop-tests/ir/whileContinue.trace | 35 +++++++++++++++++++ .../data/loop-tests/tracing/forBreak.trace | 25 +++++++++++++ .../data/loop-tests/tracing/whileBreak.trace | 21 +++++++++++ .../loop-tests/tracing/whileContinue.trace | 30 ++++++++++++++++ .../test/execution-tests/ExecutionTest.cpp | 21 +++++++++++ nautilus/test/execution-tests/TracingTest.cpp | 3 ++ 13 files changed, 306 insertions(+) create mode 100644 nautilus/test/data/loop-tests/after_ssa/forBreak.trace create mode 100644 nautilus/test/data/loop-tests/after_ssa/whileBreak.trace create mode 100644 nautilus/test/data/loop-tests/after_ssa/whileContinue.trace create mode 100644 nautilus/test/data/loop-tests/ir/forBreak.trace create mode 100644 nautilus/test/data/loop-tests/ir/whileBreak.trace create mode 100644 nautilus/test/data/loop-tests/ir/whileContinue.trace create mode 100644 nautilus/test/data/loop-tests/tracing/forBreak.trace create mode 100644 nautilus/test/data/loop-tests/tracing/whileBreak.trace create mode 100644 nautilus/test/data/loop-tests/tracing/whileContinue.trace diff --git a/nautilus/test/benchmark/TracingBenchmark.cpp b/nautilus/test/benchmark/TracingBenchmark.cpp index d03fa32e..a086c454 100644 --- a/nautilus/test/benchmark/TracingBenchmark.cpp +++ b/nautilus/test/benchmark/TracingBenchmark.cpp @@ -32,6 +32,7 @@ static auto tests = std::vector>> {"staticLoop", details::createFunctionWrapper(staticLoop)}, {"fibonacci", details::createFunctionWrapper(fibonacci)}, {"gcd", details::createFunctionWrapper(gcd)}, + {"forBreak", details::createFunctionWrapper(forBreak)}, }; TEST_CASE("Tracing Benchmark") { diff --git a/nautilus/test/common/LoopFunctions.hpp b/nautilus/test/common/LoopFunctions.hpp index d1538342..479b1b98 100644 --- a/nautilus/test/common/LoopFunctions.hpp +++ b/nautilus/test/common/LoopFunctions.hpp @@ -4,6 +4,41 @@ namespace nautilus::engine { +val forBreak(val condition) { + val result = 0; + for (val i = 0; i < 10; i = i + 1) { + if (i == condition) { + break; + } + result = result + 10; + } + return result; +} + +val whileBreak(val condition) { + val result = 0; + while (result < 100) { + if (result == condition) { + break; + } + result = result + 10; + } + return result; +} + +val whileContinue(val condition) { + val i = 0; + val result = 0; + while (i < 10) { + i++; + if (result > condition) { + continue; + } + result = result + 10; + } + return result; +} + val ifInsideLoop(val value) { val result = 0; for (val i = 0; i < value; i = i + 1) { diff --git a/nautilus/test/data/loop-tests/after_ssa/forBreak.trace b/nautilus/test/data/loop-tests/after_ssa/forBreak.trace new file mode 100644 index 00000000..3aa4fc91 --- /dev/null +++ b/nautilus/test/data/loop-tests/after_ssa/forBreak.trace @@ -0,0 +1,24 @@ +B0($1:i32) + CONST $2 0 :i32 + CONST $3 0 :i32 + CONST $4 10 :i32 + JMP $0 B5($2,$3,$1,$4) :void +B1($2:i32,$3:i32,$1:i32) + EQ $7 $3 $1 :bool + CMP $8 $7 B3($2) B4($1,$3,$2) :void +B2($2:i32) + JMP $0 B6($2) :void +B3($2:i32) + JMP $0 B6($2) :void +B4($1:i32,$3:i32,$2:i32) + CONST $11 10 :i32 + ADD $12 $2 $11 :i32 + CONST $13 1 :i32 + ADD $14 $3 $13 :i32 + CONST $15 10 :i32 + JMP $0 B5($12,$14,$1,$15) :void +B5($2:i32,$3:i32,$1:i32,$4:i32) ControlFlowMerge + LT $5 $3 $4 :bool + CMP $6 $5 B1($2,$3,$1) B2($2) :void +B6($2:i32) + RETURN $0 $2 :i32 diff --git a/nautilus/test/data/loop-tests/after_ssa/whileBreak.trace b/nautilus/test/data/loop-tests/after_ssa/whileBreak.trace new file mode 100644 index 00000000..90617005 --- /dev/null +++ b/nautilus/test/data/loop-tests/after_ssa/whileBreak.trace @@ -0,0 +1,21 @@ +B0($1:i32) + CONST $2 0 :i32 + CONST $3 100 :i32 + JMP $0 B5($2,$1,$3) :void +B1($2:i32,$1:i32) + EQ $6 $2 $1 :bool + CMP $7 $6 B3($2) B4($1,$2) :void +B2($2:i32) + JMP $0 B6($2) :void +B3($2:i32) + JMP $0 B6($2) :void +B4($1:i32,$2:i32) + CONST $10 10 :i32 + ADD $11 $2 $10 :i32 + CONST $12 100 :i32 + JMP $0 B5($11,$1,$12) :void +B5($2:i32,$1:i32,$3:i32) ControlFlowMerge + LT $4 $2 $3 :bool + CMP $5 $4 B1($2,$1) B2($2) :void +B6($2:i32) + RETURN $0 $2 :i32 diff --git a/nautilus/test/data/loop-tests/after_ssa/whileContinue.trace b/nautilus/test/data/loop-tests/after_ssa/whileContinue.trace new file mode 100644 index 00000000..36d883b4 --- /dev/null +++ b/nautilus/test/data/loop-tests/after_ssa/whileContinue.trace @@ -0,0 +1,25 @@ +B0($1:i32) + CONST $2 0 :i32 + CONST $3 0 :i32 + CONST $4 10 :i32 + JMP $0 B5($3,$2,$4,$1) :void +B1($3:i32,$1:i32,$2:i32) + CONST $8 1 :i32 + ADD $9 $2 $8 :i32 + GT $10 $3 $1 :bool + CMP $11 $10 B3($3,$9,$1) B4($9,$1,$3) :void +B2($3:i32) + RETURN $0 $3 :i32 +B3($3:i32,$2:i32,$1:i32) + CONST $12 10 :i32 + JMP $0 B5($3,$2,$12,$1) :void +B4($2:i32,$1:i32,$3:i32) + CONST $15 10 :i32 + ADD $16 $3 $15 :i32 + CONST $17 10 :i32 + JMP $0 B6($16,$2,$17,$1) :void +B5($3:i32,$2:i32,$4:i32,$1:i32) ControlFlowMerge + JMP $0 B6($3,$2,$4,$1) :void +B6($3:i32,$2:i32,$4:i32,$1:i32) ControlFlowMerge + LT $5 $2 $4 :bool + CMP $6 $5 B1($3,$1,$2) B2($3) :void diff --git a/nautilus/test/data/loop-tests/ir/forBreak.trace b/nautilus/test/data/loop-tests/ir/forBreak.trace new file mode 100644 index 00000000..f0419d13 --- /dev/null +++ b/nautilus/test/data/loop-tests/ir/forBreak.trace @@ -0,0 +1,34 @@ +NautilusIr { +execute() { +Block_0($1:i32): + $2 = 0 :i32 + $3 = 0 :i32 + $4 = 10 :i32 + br Block_5($2, $3, $1, $4) :void + +Block_5($2:i32, $3:i32, $1:i32, $4:i32): + $5 = $3 < $4 :bool + if $5 ? Block_1($2, $3, $1) : Block_2($2) :void + +Block_1($2:i32, $3:i32, $1:i32): + $7 = $3 == $1 :bool + if $7 ? Block_3($2) : Block_4($1, $3, $2) :void + +Block_3($2:i32): + br Block_6($2) :void + +Block_6($2:i32): + return ($2) :i32 + +Block_4($1:i32, $3:i32, $2:i32): + $11 = 10 :i32 + $12 = $2 + $11 :i32 + $13 = 1 :i32 + $14 = $3 + $13 :i32 + $15 = 10 :i32 + br Block_5($12, $14, $1, $15) :void + +Block_2($2:i32): + br Block_6($2) :void +} +} //NESIR \ No newline at end of file diff --git a/nautilus/test/data/loop-tests/ir/whileBreak.trace b/nautilus/test/data/loop-tests/ir/whileBreak.trace new file mode 100644 index 00000000..819ed65e --- /dev/null +++ b/nautilus/test/data/loop-tests/ir/whileBreak.trace @@ -0,0 +1,31 @@ +NautilusIr { +execute() { +Block_0($1:i32): + $2 = 0 :i32 + $3 = 100 :i32 + br Block_5($2, $1, $3) :void + +Block_5($2:i32, $1:i32, $3:i32): + $4 = $2 < $3 :bool + if $4 ? Block_1($2, $1) : Block_2($2) :void + +Block_1($2:i32, $1:i32): + $6 = $2 == $1 :bool + if $6 ? Block_3($2) : Block_4($1, $2) :void + +Block_3($2:i32): + br Block_6($2) :void + +Block_6($2:i32): + return ($2) :i32 + +Block_4($1:i32, $2:i32): + $10 = 10 :i32 + $11 = $2 + $10 :i32 + $12 = 100 :i32 + br Block_5($11, $1, $12) :void + +Block_2($2:i32): + br Block_6($2) :void +} +} //NESIR \ No newline at end of file diff --git a/nautilus/test/data/loop-tests/ir/whileContinue.trace b/nautilus/test/data/loop-tests/ir/whileContinue.trace new file mode 100644 index 00000000..7b81dbc8 --- /dev/null +++ b/nautilus/test/data/loop-tests/ir/whileContinue.trace @@ -0,0 +1,35 @@ +NautilusIr { +execute() { +Block_0($1:i32): + $2 = 0 :i32 + $3 = 0 :i32 + $4 = 10 :i32 + br Block_5($3, $2, $4, $1) :void + +Block_5($3:i32, $2:i32, $4:i32, $1:i32): + br Block_6($3, $2, $4, $1) :void + +Block_6($3:i32, $2:i32, $4:i32, $1:i32): + $5 = $2 < $4 :bool + if $5 ? Block_1($3, $1, $2) : Block_2($3) :void + +Block_1($3:i32, $1:i32, $2:i32): + $8 = 1 :i32 + $9 = $2 + $8 :i32 + $10 = $3 > $1 :bool + if $10 ? Block_3($3, $9, $1) : Block_4($9, $1, $3) :void + +Block_3($3:i32, $2:i32, $1:i32): + $12 = 10 :i32 + br Block_5($3, $2, $12, $1) :void + +Block_4($2:i32, $1:i32, $3:i32): + $15 = 10 :i32 + $16 = $3 + $15 :i32 + $17 = 10 :i32 + br Block_6($16, $2, $17, $1) :void + +Block_2($3:i32): + return ($3) :i32 +} +} //NESIR \ No newline at end of file diff --git a/nautilus/test/data/loop-tests/tracing/forBreak.trace b/nautilus/test/data/loop-tests/tracing/forBreak.trace new file mode 100644 index 00000000..7dc519c0 --- /dev/null +++ b/nautilus/test/data/loop-tests/tracing/forBreak.trace @@ -0,0 +1,25 @@ +B0($1:i32) + CONST $2 0 :i32 + CONST $3 0 :i32 + CONST $4 10 :i32 + JMP $0 B5() :void +B1() + EQ $7 $3 $1 :bool + CMP $8 $7 B3() B4() :void +B2() + RETURN $0 $2 :i32 +B3() + RETURN $0 $2 :i32 +B4() + CONST $11 10 :i32 + ADD $12 $2 $11 :i32 + ASSIGN $2 $12 :i32 + CONST $13 1 :i32 + ADD $14 $3 $13 :i32 + ASSIGN $3 $14 :i32 + CONST $15 10 :i32 + ASSIGN $4 $15 :i32 + JMP $0 B5() :void +B5() ControlFlowMerge + LT $5 $3 $4 :bool + CMP $6 $5 B1() B2() :void diff --git a/nautilus/test/data/loop-tests/tracing/whileBreak.trace b/nautilus/test/data/loop-tests/tracing/whileBreak.trace new file mode 100644 index 00000000..4cfa2a73 --- /dev/null +++ b/nautilus/test/data/loop-tests/tracing/whileBreak.trace @@ -0,0 +1,21 @@ +B0($1:i32) + CONST $2 0 :i32 + CONST $3 100 :i32 + JMP $0 B5() :void +B1() + EQ $6 $2 $1 :bool + CMP $7 $6 B3() B4() :void +B2() + RETURN $0 $2 :i32 +B3() + RETURN $0 $2 :i32 +B4() + CONST $10 10 :i32 + ADD $11 $2 $10 :i32 + ASSIGN $2 $11 :i32 + CONST $12 100 :i32 + ASSIGN $3 $12 :i32 + JMP $0 B5() :void +B5() ControlFlowMerge + LT $4 $2 $3 :bool + CMP $5 $4 B1() B2() :void diff --git a/nautilus/test/data/loop-tests/tracing/whileContinue.trace b/nautilus/test/data/loop-tests/tracing/whileContinue.trace new file mode 100644 index 00000000..2597baa3 --- /dev/null +++ b/nautilus/test/data/loop-tests/tracing/whileContinue.trace @@ -0,0 +1,30 @@ +B0($1:i32) + CONST $2 0 :i32 + CONST $3 0 :i32 + CONST $4 10 :i32 + JMP $0 B5() :void +B1() + ASSIGN $7 $2 :i32 + CONST $8 1 :i32 + ADD $9 $2 $8 :i32 + ASSIGN $2 $9 :i32 + GT $10 $3 $1 :bool + CMP $11 $10 B3() B4() :void +B2() + RETURN $0 $3 :i32 +B3() + CONST $12 10 :i32 + ASSIGN $4 $12 :i32 + JMP $0 B5() :void +B4() + CONST $15 10 :i32 + ADD $16 $3 $15 :i32 + ASSIGN $3 $16 :i32 + CONST $17 10 :i32 + ASSIGN $4 $17 :i32 + JMP $0 B6() :void +B5() ControlFlowMerge + JMP $0 B6() :void +B6() ControlFlowMerge + LT $5 $2 $4 :bool + CMP $6 $5 B1() B2() :void diff --git a/nautilus/test/execution-tests/ExecutionTest.cpp b/nautilus/test/execution-tests/ExecutionTest.cpp index 36739c0a..ef848346 100644 --- a/nautilus/test/execution-tests/ExecutionTest.cpp +++ b/nautilus/test/execution-tests/ExecutionTest.cpp @@ -458,6 +458,27 @@ void loopExecutionTest(engine::NautilusEngine& engine) { REQUIRE(f(10) == 101); REQUIRE(f(0) == 1); } + SECTION("forBreak") { + auto f = engine.registerFunction(forBreak); + REQUIRE(f(10) == 100); + REQUIRE(f(1) == 10); + REQUIRE(f(2) == 20); + REQUIRE(f(0) == 0); + } + SECTION("whileBreak") { + auto f = engine.registerFunction(whileBreak); + REQUIRE(f(42) == 100); + REQUIRE(f(40) == 40); + REQUIRE(f(20) == 20); + REQUIRE(f(0) == 0); + } + SECTION("whileContinue") { + auto f = engine.registerFunction(whileContinue); + REQUIRE(f(20) == 30); + REQUIRE(f(22) == 30); + REQUIRE(f(50) == 60); + REQUIRE(f(1000) == 100); + } SECTION("nestedSumLoop") { auto f = engine.registerFunction(nestedSumLoop); REQUIRE(f(10) == 1001); diff --git a/nautilus/test/execution-tests/TracingTest.cpp b/nautilus/test/execution-tests/TracingTest.cpp index 9b705809..ea7be08d 100644 --- a/nautilus/test/execution-tests/TracingTest.cpp +++ b/nautilus/test/execution-tests/TracingTest.cpp @@ -263,6 +263,9 @@ TEST_CASE("Loop Trace Test") { {"digitSum", details::createFunctionWrapper(digitSum)}, {"sumOfSquares", details::createFunctionWrapper(sumOfSquares)}, {"countDigits", details::createFunctionWrapper(countDigits)}, + {"forBreak", details::createFunctionWrapper(forBreak)}, + {"whileBreak", details::createFunctionWrapper(whileBreak)}, + {"whileContinue", details::createFunctionWrapper(whileContinue)}, }; runTraceTests("loop-tests", tests); }