LoopInvariantCodeMotion: `struct.new` is hoisted out of a loop, so all iterations share one object
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 68/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- wasm
- Área
- compilers
Línea de trabajo
Start with the LoopInvariantCodeMotion pass and its unsafeToMove logic, then reproduce the issue with the supplied WAT module using wasm-opt --enable-gc --enable-reference-types --licm --fuzz-exec. Check that struct.new remains per-iteration and that the optimized and unoptimized executions both return 1.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
unsafeToMove does not treat an allocation as generative, so local.set $x (struct.new ...) is moved out of the loop and every iteration mutates the same object.
Root cause
struct.new is considered movable because it has no side effect on existing state, but it creates a new identity on each evaluation.
Affected passes
Only LoopInvariantCodeMotion. Allocations in other loop-hoisting code were not examined.
Reproducer
In C-like pseudo code, the function below is:
struct T { int f; };
int f(void) {
struct T *x;
int i = 0;
do {
x = new_T(0); // a new object on every iteration
x->f = x->f + 1;
i = i + 1;
} while (i < 2);
return x->f; // 1
}
After --licm, new_T(0) is moved above the loop, so both iterations update the same object and f returns 2:
x = new_T(0);
do {
x->f = x->f + 1;
i = i + 1;
} while (i < 2);
return x->f; // 2
(module
(type $T (struct (field (mut i32))))
(func (export "f") (result i32)
(local $x (ref null $T)) (local $i i32)
(loop $l
(local.set $x (struct.new $T (i32.const 0)))
(struct.set $T 0 (local.get $x)
(i32.add (struct.get $T 0 (local.get $x)) (i32.const 1)))
(br_if $l (i32.lt_u (local.tee $i (i32.add (local.get $i) (i32.const 1))) (i32.const 2))))
(struct.get $T 0 (local.get $x))))
$ wasm-opt in.wat --enable-gc --enable-reference-types --licm --fuzz-exec -o /dev/null
[fuzz-exec] export f
[fuzz-exec] note result: f => 1
[fuzz-exec] export f
[fuzz-exec] note result: f => 2
[fuzz-exec] comparing f
values not identical! 2 != 1
[fuzz-exec] optimization passes changed results
Expected vs actual
The original returns 1 (each iteration starts from a fresh object). After the pass the object is shared across the two iterations and the function returns 2.
Version
Reproduced on upstream main at 4d8ac549e2ab9b283246ea95e79ebe139ca579ac (wasm-opt version 133).
AI was used as part of the process of finding this issue. I have manually checked and reproduced it.
- Lenguaje dominante
- WebAssembly
- Estrellas
- 8.7k
- Forks
- 893
- Merge medio
- 1 d 15 h
- PR fusionados (30 d)
- 79
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de WebAssembly/binaryen
-
AvoidReinterprets: `i32.atomic.load` under `f32.reinterpret_i32` loses its atomicityPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
WebAssembly/binaryen#9185 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
WebAssembly/binaryen#9135 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 Medio día Aptitud para principiantes 76/100
WebAssembly/binaryen#9018 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
TupleOptimization: tuple swap is miscompiledPosiblemente ocupada @tlively la tomó hace 2 días. Abierto
Dificultad 3/5 1-2 días Aptitud para principiantes 58/100
WebAssembly/binaryen#9210 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 52/100
WebAssembly/binaryen#9186 ·
Los mantenedores suelen responder en 1 día
Todos los issues de WebAssembly/binaryen
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
objectionary/eo#9317 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
rubys/roundhouse#571 ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
anthropics/buffa#639 ·
Los mantenedores suelen responder en 3 días
-
Module EQUIVALENCE into an array with a non-default lower bound ignores the bound (wrong element)Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
Los mantenedores suelen responder en 1 día
-
Discover carries headerEdges that nothing reads since #1914 moved E0507/E0517 to the compiler graphAbiertotech-debt
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
Los mantenedores suelen responder en 1 día