Skip to content

Commit 51aacba

Browse files
authored
Merge pull request #295 from TurboWarp/optimize-loops
Optimize loops with provably-non-fraction iteration counts
2 parents 5c5ff71 + 2a2d152 commit 51aacba

25 files changed

+45
-41
lines changed

src/compiler/jsgen.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,11 @@ class JSGenerator {
610610
break;
611611
case StackOpcode.CONTROL_REPEAT: {
612612
const i = this.localVariables.next();
613-
this.source += `for (var ${i} = ${this.descendInput(node.times)}; ${i} >= 0.5; ${i}--) {\n`;
613+
if (node.times.isAlwaysType(InputType.NUMBER_INT | InputType.NUMBER_INF)) {
614+
this.source += `for (var ${i} = ${this.descendInput(node.times)}; ${i} > 0; ${i}--) {\n`;
615+
} else {
616+
this.source += `for (var ${i} = ${this.descendInput(node.times)}; ${i} >= 0.5; ${i}--) {\n`;
617+
}
614618
this.descendStack(node.do, new Frame(true));
615619
this.yieldLoop();
616620
this.source += `}\n`;

test/snapshot/__snapshots__/tw-analyze-yields-due-to-direct-recursion.sb3.tw-snapshot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ return "";
3131
(function factoryXYZ(thread) { const target = thread.target; const runtime = target.runtime; const stage = runtime.getTargetForStage();
3232
const b0 = stage.variables["`jEk@4|i[#Fk?(8x)AV.-my variable"];
3333
return function* genXYZ () {
34-
for (var a0 = 1; a0 >= 0.5; a0--) {
34+
for (var a0 = 1; a0 > 0; a0--) {
3535
yield;
3636
}
3737
b0.value = "random";

test/snapshot/__snapshots__/tw-comparison-matrix-runtime.sb3.tw-snapshot

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ return function* genXYZ_run_test () {
2323
thread.procedures["Wsetup values"]();
2424
b0.value = 0;
2525
b1.value = 0;
26-
for (var a0 = b2.value.length; a0 >= 0.5; a0--) {
26+
for (var a0 = b2.value.length; a0 > 0; a0--) {
2727
b1.value = ((+b1.value || 0) + 1);
2828
b3.value = 0;
29-
for (var a1 = b2.value.length; a1 >= 0.5; a1--) {
29+
for (var a1 = b2.value.length; a1 > 0; a1--) {
3030
b3.value = ((+b3.value || 0) + 1);
3131
b0.value = ((+b0.value || 0) + 1);
3232
if (!compareEqual(compareGreaterThan(listGet(b2.value, b1.value), (b2.value[(b3.value | 0) - 1] ?? "")), (b4.value[(b0.value | 0) - 1] ?? ""))) {

test/snapshot/__snapshots__/tw-counter.sb3.tw-snapshot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ runtime.ext_scratch3_control._counter = 0;
3232
if ((runtime.ext_scratch3_control._counter === 0)) {
3333
yield* executeInCompatibilityLayer({"MESSAGE":"pass clear = 0",}, b0, false, false, "w", null);
3434
}
35-
for (var a0 = 10; a0 >= 0.5; a0--) {
35+
for (var a0 = 10; a0 > 0; a0--) {
3636
runtime.ext_scratch3_control._counter++;
3737
yield;
3838
}

test/snapshot/__snapshots__/tw-exit-state-accounts-for-yields-in-procedures.sb3.tw-snapshot

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ retire(); return;
2020
// Sprite1 Zsomething that yields
2121
(function factoryXYZ(thread) { const target = thread.target; const runtime = target.runtime; const stage = runtime.getTargetForStage();
2222
return function* genXYZ_something_that_yield () {
23-
for (var a0 = 2; a0 >= 0.5; a0--) {
23+
for (var a0 = 2; a0 > 0; a0--) {
2424
yield;
2525
}
2626
return "";
@@ -30,7 +30,7 @@ return "";
3030
(function factoryXYZ(thread) { const target = thread.target; const runtime = target.runtime; const stage = runtime.getTargetForStage();
3131
const b0 = stage.variables["`jEk@4|i[#Fk?(8x)AV.-my variable"];
3232
return function* genXYZ () {
33-
for (var a0 = 1; a0 >= 0.5; a0--) {
33+
for (var a0 = 1; a0 > 0; a0--) {
3434
yield;
3535
}
3636
b0.value = "random";

test/snapshot/__snapshots__/tw-forkphorus-515-wait-zero-seconds-in-warp-mode.sb3.tw-snapshot

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ retire(); return;
2626
const b0 = runtime.getOpcodeFunction("music_restForBeats");
2727
const b1 = runtime.getOpcodeFunction("music_playDrumForBeats");
2828
return function* genXYZ_no_refresh () {
29-
for (var a0 = 30; a0 >= 0.5; a0--) {
29+
for (var a0 = 30; a0 > 0; a0--) {
3030
thread.timer = timer();
3131
var a1 = Math.max(0, 1000 * 0);
3232
runtime.requestRedraw();
@@ -53,7 +53,7 @@ return "";
5353
const b0 = runtime.getOpcodeFunction("music_restForBeats");
5454
const b1 = runtime.getOpcodeFunction("music_playDrumForBeats");
5555
return function* genXYZ_has_refresh () {
56-
for (var a0 = 30; a0 >= 0.5; a0--) {
56+
for (var a0 = 30; a0 > 0; a0--) {
5757
thread.timer = timer();
5858
var a1 = Math.max(0, 1000 * 0);
5959
runtime.requestRedraw();

test/snapshot/__snapshots__/tw-gh-249-quicksort.sb3.tw-snapshot

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const b0 = stage.variables["EF^k=u-t@S)w60;RP?dZ-list-list"];
1818
const b1 = stage.variables["rQq!wAuU2T9DV9,S[/s."];
1919
return function funXYZ_run () {
2020
b0.value = [];
21-
for (var a0 = 100; a0 >= 0.5; a0--) {
21+
for (var a0 = 100; a0 > 0; a0--) {
2222
b0.value.push((b1.value[(b0.value.length + 1) - 1] ?? ""));
2323
b0._monitorUpToDate = false;
2424
}
@@ -36,7 +36,7 @@ const b4 = runtime.getOpcodeFunction("looks_say");
3636
return function* genXYZ_validate () {
3737
b0.value = 1;
3838
b1.value = 1;
39-
for (var a0 = b2.value.length; a0 >= 0.5; a0--) {
39+
for (var a0 = b2.value.length; a0 > 0; a0--) {
4040
if (!compareEqual((b2.value[(b1.value | 0) - 1] ?? ""), (b3.value[(b1.value | 0) - 1] ?? ""))) {
4141
b0.value = 0;
4242
yield* executeInCompatibilityLayer({"MESSAGE":("fail mismatch at index " + ("" + b1.value)),}, b4, true, false, ",", null);

test/snapshot/__snapshots__/tw-preciseProjectTimer-drift-453118719.sb3.tw-snapshot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const b2 = stage.variables["l^q!%fq]Bv;72dlGf}^Z"];
99
return function* genXYZ () {
1010
b0.value = 0;
1111
yield* executeInCompatibilityLayer({"MESSAGE":"plan 0",}, b1, false, false, "}fY]VN(X|v/[G`P0?@s2", null);
12-
for (var a0 = 30; a0 >= 0.5; a0--) {
12+
for (var a0 = 30; a0 > 0; a0--) {
1313
b2.value = runtime.ioDevices.clock.projectTimer();
1414
thread.timer = timer();
1515
var a1 = Math.max(0, 1000 * 0);

test/snapshot/__snapshots__/tw-procedure-return-stops-scripts.sb3.tw-snapshot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const b0 = stage.variables["PsAI*C{QHI3*4?O8p#TM"];
2525
const b1 = runtime.getOpcodeFunction("looks_say");
2626
return function* genXYZ_return_stops_the_scr () {
2727
b0.value = 0;
28-
for (var a0 = 100; a0 >= 0.5; a0--) {
28+
for (var a0 = 100; a0 > 0; a0--) {
2929
b0.value = (b0.value + 1);
3030
if ((b0.value === 25)) {
3131
return "stopped!";

test/snapshot/__snapshots__/tw-procedure-return-warp.sb3.tw-snapshot

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const b0 = stage.variables["Go=PJS7BFXYo_qi2S:kQ"];
3838
const b1 = runtime.getOpcodeFunction("looks_say");
3939
return function* genXYZ_non_warp () {
4040
b0.value = 0;
41-
for (var a0 = 5; a0 >= 0.5; a0--) {
41+
for (var a0 = 5; a0 > 0; a0--) {
4242
thread.timer = timer();
4343
var a1 = Math.max(0, 1000 * 0);
4444
runtime.requestRedraw();
@@ -56,7 +56,7 @@ if ((("" + (yield* thread.procedures["Wverify runs warp %s"]((yield* thread.proc
5656
yield* executeInCompatibilityLayer({"MESSAGE":"pass non warp and warp mix",}, b1, false, false, "S", null);
5757
}
5858
b0.value = 0;
59-
for (var a2 = 5; a2 >= 0.5; a2--) {
59+
for (var a2 = 5; a2 > 0; a2--) {
6060
thread.timer = timer();
6161
var a3 = Math.max(0, 1000 * 0);
6262
runtime.requestRedraw();
@@ -79,7 +79,7 @@ const b0 = stage.variables["Go=PJS7BFXYo_qi2S:kQ"];
7979
const b1 = runtime.getOpcodeFunction("looks_say");
8080
return function* genXYZ_verify_runs_warp_ (p0) {
8181
b0.value = 0;
82-
for (var a0 = 5; a0 >= 0.5; a0--) {
82+
for (var a0 = 5; a0 > 0; a0--) {
8383
thread.timer = timer();
8484
var a1 = Math.max(0, 1000 * 0);
8585
runtime.requestRedraw();
@@ -101,7 +101,7 @@ const b0 = stage.variables["Go=PJS7BFXYo_qi2S:kQ"];
101101
const b1 = runtime.getOpcodeFunction("looks_say");
102102
return function* genXYZ_verify_runs_non_warp (p0) {
103103
b0.value = 0;
104-
for (var a0 = 5; a0 >= 0.5; a0--) {
104+
for (var a0 = 5; a0 > 0; a0--) {
105105
thread.timer = timer();
106106
var a1 = Math.max(0, 1000 * 0);
107107
runtime.requestRedraw();

0 commit comments

Comments
 (0)