LLVM intrinsics do not support out params. To get around this limitation implementers will make intrinsics return structs to capture a return type and an out param. The number of struct elements will grow per out parameter.
This presents our first problem with the Scalarizer Pass. If the return type is not a vector then the intrinsic won’t be scalarized even though it is trivial to do so.
To capture this trivial case the proposal is to scalarize structs if the struct elements are all FixedVectorType and if the vectors in the struct match the vector size of the input parameter.
To support this trivial case only three changes are needed to the scalarizer pass.
- A change is needed to the Instruction Vistor for CallInst so that the Struct element type is used for
getVectorSplit - A
visitExtractValueInstneeds to be added so that ExtractValues which fetch the vectors off the struct and can scalarize those vectors. - The finish function needs to be updated to handle structs so that
replaceAllUsesWithis able to replace the struct uses with a type equivalent scalarization.
Why should we do this?
First it would allow the scalarizer pass to support intrinsics that are used by clang builtins\functions that have out parameter.
Second HLSL has out parameter apis like asuint with a godbolt example.
For the DirectX target this would either need to have custom scalarization done in cgbuiltins or in the DirectX backend. Given that there are other APIs with “out params” that are elementwise operations in HLSL this will become a compounding problem of HLSL APIs that need custom scalarization. Part of our hope of using the scalarizer pass was that it would be a pass that would let us do legal DXIL with little to no custom scalarization.
Example implementation: https://github.com/llvm/llvm-project/compare/main...farzonl:llvm-project:scalarize-structs