Issue 137946
Summary [WebAssembly] Result unnecessarily stored in two locations
Labels
Assignees
Reporter Photosounder
    I found something strange while looking at a Wasm binary compiled from C with the latest Clang. This function:

```c
typedef struct { double x, y; } xy_t;

xy_t mul_xy(xy_t a, xy_t b)
{
	a.x *= b.x;
	a.y *= b.y;
	return a;
}
```

compiles, using `-msimd128 -Oz`, to this:

![Image](https://github.com/user-attachments/assets/b67d026d-40e0-4068-89e8-2e13d138e58e)
(the squares on the left are the bytes from the .wasm, the grey rectangle is their interpretation, the purple rectangle is their C decompilation and the blue rectangle is the stack height change)

or in WAT format:

```
mul_xy:
 local.get       1
        local.get       2
        v128.load 0:p2align=3
        local.get       1
        v128.load       0:p2align=3
 f64x2.mul
        v128.store      0:p2align=3
        local.get 0
        local.get       1
        v128.load       0:p2align=3
 v128.store      0:p2align=3
        end_function
```

In Wasm `mul_xy` now has 3 arguments as pointers, `local0` points to where the result is actually wanted, `local1` points to vector `a` and `local2` points to vector `b`. The problem is that whereas you'd expect the f64x2 multiplication to be stored directly at `local0`, it's instead first stored at `local1`, then the vector at `local1` is reloaded to be stored at `local0`. So we needlessly do some extra memory operations plus we force the caller to handle how the value of `a` will be modified when that's not what we want (although it seems that the values get copied to the stack regardless).

If I modify the C function to this:

```c
xy_t mul_xy(xy_t a, xy_t b)
{
        xy_t c;
	c.x = a.x * b.x;
	c.y = a.y * b.y;
	return c;
}
```

then it compiles to the correct expect Wasm:

```
mul_xy:
        local.get       0
 local.get       1
        v128.load       0:p2align=3
        local.get 2
        v128.load       0:p2align=3
        f64x2.mul
 v128.store      0:p2align=3
        end_function
```

So there's something wrong with how the compiler doesn't realise that the two versions of the C function are functionally the same.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to