Issue 170777
Summary [HLSL][Matrix] Support MatrixSingleSubscript Dynamic Index Swizzle
Labels new issue
Assignees
Reporter farzonl
    The introduction of the `MatrixSingleSubscriptExpr` AST type meant we needed a
custom emitter in `EmitMatrixSingleSubscriptExpr` which meant we needed a new 
`MatrixRow` Lvalue type because `ExtVectorElt` had a requirment for constant 
indicies. We can still use `MakeExtVectorElt` but only if the row index is 
constant. For now if we don't have them then `EmitExtVectorElementExpr` fails.
Like so:
```cpp
  if (Base.isMatrixRow())
    return EmitUnsupportedLValue(E, "Matrix single index swizzle");
```

That means today the following cases work
```hlsl
export float4 getMatrix(float4x4 M, int index) {
    return M[index];
}

export void setMatrix(out float4x4 M, int index, float4 V) {
    M[index] = V;
}

export void setMatrix2(out float4x4 M, float4 V) {
    M[3].abgr = V;
}

export void setMatrix3(out float4x4 M, float4 V) {
    M[1].rgba = V;
}
```

That also means this doesn't work
```hlsl
export void setMatrix4(out float4x4 M, int index, float4 V) {
    M[index].abgr = V;
}

export float3 getMatrix2(float4x4 M, int index) {
    return M[index].rgb;
}
```

This failing case while visually similar to swizzling on an array of vectors is
very different. for an array-of-vectors, the “hard part” (the dynamic index) is
already solved before the swizzle ever sees it. For matrices, you’re trying to
push that dynamic index into the swizzle layer, where it fundamentally doesn’t
fit. Example
```hlsl
float4 v[10];
float2 x = v[i].xy;
```
The AST just treates the array subscript as a base:
```
ArraySubscriptExpr( base = v, idx = i ) --> type float4
ExtVectorElementExpr( base = ArraySubscriptExpr, "xy" )
```

Crucially: the dynamic index i is already baked into the pointer. The LValue 
itself doesn’t need to remember i separately. MakeExtVectorElt only needs:

1. “where is the vector?” → baseLV.getAddress()
2. “which components (xy)?” → constant mask {0, 1}

That’s why arrays-of-vectors don’t have your problem: the dynamic part (i) is
entirely handled by the array-subscript lvalue; the swizzle only deals with
constant component selection inside a single, already-chosen vector.

With matrices, what you want conceptually is very similar:
```hlsl
float4x4 M;
float2 x = M[row].xy;
```

But the the difference is Clang’s matrix extension doesn’t model a matrix as
“array of row-vectors” or “array of col-vectors” at the IR level. Its
represented as one singular vector. For example the ir would look like
```llvm
instruction <16 x float>  // for a 4x4, flattened
```

## Plan(s)
1. Keep flattened representation but add custom row abstraction
   - The “swizzle” logic has to special-case “base is matrix-row” and do the right gather/scatter.

_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to