<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/99172>99172</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Implement the `WavePrefixSum` HLSL Function
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            metabug,
            backend:DirectX,
            HLSL,
            backend:SPIR-V,
            bot:HLSL
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          farzonl
      </td>
    </tr>
</table>

<pre>
    - [ ] Implement `WavePrefixSum` clang builtin,
- [ ] Link `WavePrefixSum` clang builtin with `hlsl_intrinsics.h`
- [ ] Add sema checks for `WavePrefixSum` to `CheckHLSLBuiltinFunctionCall` in `SemaChecking.cpp`
- [ ] Add codegen for `WavePrefixSum` to `EmitHLSLBuiltinExpr` in `CGBuiltin.cpp`
- [ ] Add codegen tests to `clang/test/CodeGenHLSL/builtins/WavePrefixSum.hlsl`
- [ ] Add sema tests to `clang/test/SemaHLSL/BuiltIns/WavePrefixSum-errors.hlsl`
- [ ] Create the `int_dx_WavePrefixSum` intrinsic in `IntrinsicsDirectX.td`
- [ ] Create the `DXILOpMapping` of `int_dx_WavePrefixSum` to  `121` in `DXIL.td`
- [ ] Create the  `WavePrefixSum.ll` and `WavePrefixSum_errors.ll` tests in `llvm/test/CodeGen/DirectX/`
- [ ] Create the `int_spv_WavePrefixSum` intrinsic in `IntrinsicsSPIRV.td`
- [ ] In SPIRVInstructionSelector.cpp create the `WavePrefixSum` lowering and map  it to `int_spv_WavePrefixSum` in `SPIRVInstructionSelector::selectIntrinsic`.
- [ ] Create SPIR-V backend test case in `llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WavePrefixSum.ll`

## DirectX

| DXIL Opcode | DXIL OpName | Shader Model | Shader Stages |
| ----------- | ----------- | ------------ | ------------- |
| 121 | WavePrefixOp | 6.0 | ('library', 'compute', 'amplification', 'mesh', 'pixel', 'vertex', 'hull', 'domain', 'geometry', 'raygeneration', 'intersection', 'anyhit', 'closesthit', 'miss', 'callable', 'node') |

## SPIR-V

# [OpGroupNonUniformFAdd](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpGroupNonUniformFAdd):

## Description:
  
A floating point add [group operation](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Group_Operation) of all *Value*
operands contributed by active [invocations](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Invocation) in the
[group](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Group).  
  
*Result Type* must be a scalar or vector of [*floating-point
type*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Floating).  
  
*Execution* is a [*Scope*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Scope_-id-) that identifies the group of
invocations affected by this command. It must be **Subgroup**.  
  
The identity *I* for *Operation* is 0. If *Operation* is
**ClusteredReduce**, *ClusterSize* must be present.  
  
The type of *Value* must be the same as *Result Type*. The method used
to perform the group operation on the contributed *Value*(s) from active
invocations is implementation defined.  
  
*ClusterSize* is the size of cluster to use. *ClusterSize* must be a
scalar of [*integer type*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Integer), whose *Signedness* operand is 0.
*ClusterSize* must come from a [*constant
instruction*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#ConstantInstruction). Behavior is undefined unless
*ClusterSize* is at least 1 and a power of 2. If *ClusterSize* is
greater than the size of the [group](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Group), executing this instruction
results in undefined behavior.

[Capability](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Capability):  
**GroupNonUniformArithmetic**, **GroupNonUniformClustered**,
**GroupNonUniformPartitionedNV**  
  
[Missing before](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Unified) **version 1.3**.

<table>
<colgroup>
<col style="width: 12%" />
<col style="width: 12%" />
<col style="width: 12%" />
<col style="width: 12%" />
<col style="width: 12%" />
<col style="width: 12%" />
<col style="width: 12%" />
<col style="width: 12%" />
</colgroup>
<thead>
<tr>
<th>Word Count</th>
<th>Opcode</th>
<th>Results</th>
<th>Operands</th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p>6 + variable</p></td>
<td class="tableblock halign-left valign-top"><p>350</p></td>
<td
class="tableblock halign-left valign-top"><p><em>&lt;id&gt;</em><br />
<em>Result Type</em></p></td>
<td class="tableblock halign-left valign-top"><p><a
href="#ResultId"><em>Result &lt;id&gt;</em></a></p></td>
<td class="tableblock halign-left valign-top"><p><a
href="#Scope_-id-"><em>Scope &lt;id&gt;</em></a><br />
<em>Execution</em></p></td>
<td class="tableblock halign-left valign-top"><p><a
href="#Group_Operation"><em>Group Operation</em></a><br />
<em>Operation</em></p></td>
<td
class="tableblock halign-left valign-top"><p><em>&lt;id&gt;</em><br />
<em>Value</em></p></td>
<td class="tableblock halign-left valign-top"><p>Optional<br />
<em>&lt;id&gt;</em><br />
<em>ClusterSize</em></p></td>
</tr>
</tbody>
</table>



## Test Case(s)

 
 ### Example 1
```hlsl
//dxc WavePrefixSum_test.hlsl -T lib_6_8 -enable-16bit-types -O0

export float4 fn(float4 p1) {
    return WavePrefixSum(p1);
}
```
 ### Example 2
```hlsl
//dxc WavePrefixSum_1_test.hlsl -T lib_6_8 -enable-16bit-types -O0

export uint4 fn(uint4 p1) {
    return WavePrefixSum(p1);
}
```
 ### Example 3
```hlsl
//dxc WavePrefixSum_2_test.hlsl -T lib_6_8 -enable-16bit-types -O0

export int4 fn(int4 p1) {
    return WavePrefixSum(p1);
}
```
## HLSL:

Returns the sum of all of the values in the active lanes with smaller indices than this one.

## Syntax

``` syntax
<type> WavePrefixSum(
   <type> value
);
```

## Parameters

*value* 

The value to sum up.

## Return value

The sum of the values.

## Remarks

The order of operations on this routine cannot be guaranteed. So, effectively, the \[precise\] flag is ignored within it.

A postfix sum can be computed by adding the prefix sum to the current lane's value.

Note that the active lane with the lowest index will always receive a 0 for its prefix sum.

This function is supported from shader model 6.0 in all shader stages. 

## Examples

```hlsl
uint numToSum = 2;
uint prefixSum = WavePrefixSum( numToSum );
```

On a machine with a wave size of 8, and all lanes active except lanes 0 and 4, the following values would be returned from WavePrefixSum.

| lane index | status   | prefixSum     | 
|------------|----------|---------------|
| 0          | inactive | n/a           |
| 1          | active   | = 0           |
| 2          | active   | = 0+2         |
| 3          | active   | = 0+2+2       |
| 4          | inactive | n/a           |
| 5          | active   | = 0+2+2+2     |
| 6          | active   | = 0+2+2+2+2   |
| 7          | active   | = 0+2+2+2+2+2 |

## See also

[Overview of Shader Model 6](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src//direct3dhlsl/hlsl-shader-model-6-0-features-for-direct3d-12.md)

[Shader Model 6](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src//direct3dhlsl/shader-model-6-0.md)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWl9v2zgS_zTMC2FBpmI7eciD4tR7BtqmaLrdfQsocWzxSpECSTnxfvoD_8iSYifZ9Da793BF0ZpDzr_fzNDk0NQYvpUAV2h2jWY3Z7S1ldJXG6r_UFKcFYrtryYYza4xmt3gdd0IqEFajObpb3QHXzRs-ONdW6N5iktB5RYXLReWS0SWKM171o9c_nidCz9wW7lllTDinkuruTS8NEmF5ulIXs4YNlBTXFZQ_jB4o_RJ8VY58tIt-tfHu4_XQc-qlaXlSi6pEG4Vl27VHdTUr-Rym5RNc0pnqRhsQb6i70PN7UDdh8dG92qWv0TyazosGGuiRA8TIitHQ2S1VAx-Ael0ILKK6BlEViODEgfjs8i9IN4hEWV7W9fHsiegtdLmpIqlBmoB2wqcbC7tPXu8P4LqEN6Iy_oQ7huuobS_J5a9LPnm9_XH2-YTbRout06k2ryk0Crspqdk2gfDiXhZz1GYk5AzVLKjqfsISlgRAA56hNjVR-FDZBVdRWT1Ooim2b0Fxbsv66_fT_i2lthPraWxuvV1cAcCSqu0y0hcjhQfKRTqATSXWw9ATRuMuY1Z9IKRvr6e0YqyHGW58aOD-WieJqfwcEIm33FByx8gmccYl9TAKzh73YisXLpO-o3lqGJETGb3l2SIZLiLUKAtltilDL5tXJXiwfgzrcP4rqIMNP6kGIgh4c7SLRhHiYIm_R_8yviYMBkImpKpn-9duW08YZ6k_n9ELhBZCF5oqveILBBxtEWp6qa10BNo3Qi-4SV14enJNZiqHzX8EUQ_3IG28NiPq1YMZpmqKR-I2oKqwQ6N0HS_BQn6iU4uLWgD5ZhK5b7iduCBUAaMHdFqbsxgBRWCFmLgpFQsjC47CA-xDsl1ILncu21-0aptPiv5q-QbpetVzhia3SByUVnbGJe8ZIXISsOWG6v3yY9KK6lMovQ2Jt7EZZ5pwOdbK_mGA5t2SZlUthaIZKcVkUunYJSPYErNG4-Ln8IYpXmON0JR6-qyUVxaTBlz5m-dTKyaDt93MNybfX97UEEu3T5MhcCI5N-paAERZ6c3QjKDS-Xqr2gtMFzsMS0t34EzlsudCrln3sPQ9UG8s5FLt8U5XCNK74YNIpeJD5L_B5H8K5hWWPxt3zhocN0aiwvAFJuSCqqx0njnd0b_hTa7RiTvojvx0UVpbgPzexi9irqO7P7wCGUb8MsxN5hG4-5K9W7GeNn3E84mLmi2ohZzBtK61cZ_ScUU36A0HyQQppsNlDHFbMVd2tU1lSzBa3uA3BlN8ru2CBngRwOfv1UQtdm9W7t2jvujH8kHCe_BSBO83pyYCNAhki9FayxoYF-BtSUEYtiTurk7_scoIxoNBqR9YpELvc-MvrwOHA4Q476JqMFHmZZgx16DrRTDrQHm8kjhBrTbb4Zgdi5g5atkVLLDqiYXxoVlo1Ud6_hJFLjBvLs1BIkMNlwCG2fWE_95iKzhf3hHyzDrThmtgeQFwChK866IutJx3yRbx_1-FbMOKtxuTZb4oVLGp9adu1sxCe77KMdx_wu5ctJt70WpaoiARgdKJY2lvup5f3p6J1eWUdl6qOkywddQ0R1X2pnfyhhE3ErhvHsmhtRiAdRYPPWHRYobd3Z0kSFdsRwxoTTf-pOedsUuR3ngj6R_w27tgghhr5PbsHkMgU9z7cvKn-17LIqIUBK_rmfXS9rQggtu9-8SqV66PyV0tYRI_uQkkWtuqxosL0ebzvHCwxZ1WPecyC9UW-7QAPb5e1gxKOjZ9SdujAOvgI3S8B7u_xro_hjn9e9AG7fBTJMsbuQxENnS-hNg9iGMSiVCCg0I2Ni9W3KDCHngzFYO0ClBZIYIwc7i_y_-rxcjsjrC3lZAWT_SgwmUffhNaYaXqpU2sHviYD5cw07Phe8-8xxjOIyenn0Hqhvp0WjseKHY_iQMDJeCGhPw9YlcCFX-wBUVfCsnAjYW78JnqxpESNDuEJ5jRK7xjmoe8t-pbXrj2F-iJJulL0pGaf7TslG2hNr9T-bCouyaM0TmW_cpKAqT2bLQozzz5OHRZ7T4PUBA2dIdPSoNm8COSBYMWLPDwqFZr3mEyIr-veYOD9pDgz39DfaeikV_cfhHInF0Qx365ydxP_kGt55n-h-rhXBef3fsb31XgopnrPgZy4fnwz9l__E-O9pZHWFwGEjHvZVvYCxeUgPxYhMm_bkmrHCLPjxSd6PBUzc7T8Nf3wZP49GGPZZ43Be2YKxvlePJNyx4cT-_v8ATkM6UyXRecDtx1xODJ7ex-wiPjdI2dHXO8UYichE_N9PQurr2xy2MNdhWy7FCRC78ModxmqPFzdDW0-6QN7gz_XmHWi47f8LHd3Ine4M75Ofd6b35y5yJjvj3l67399XLibfitu4abPFOtHPlbWJHq-unCSrBhAc1U1MhQGMuGS9918RfrLjBSkIy7oDupaWPkdQZhc2Bmi39NTr7cORTOPwvCcrTwSpvmhff-Tv09KD2C9W0BgvadOR817U2AuVb5ye2ykPQNmPLA0S9wsASwepRespUU_3D9OuVZuGGemiBmNAD4QZr5S6EgEsqpfLthm1LNZUWgCX4Tvlro-868R2IvRuGG-sSza4bDSU34Ac3eCPo1vdGtlJpYD5MXGJuo3k5bpSxG_7oHSipdNpiuz40TRkLd1PfJOoWWhW6Na3WIK1PAUQWJrgeRX9W_nGH2qfJEnLFEYV6cBshlwwe8QMXAlPxQPcGayjBLac49W0wbs1AfdLByA3exBdW56RpG1crwEJbw4TnkNq_j8wT_zrkkjnSjX8mSfAoTrGqzZPEjHXtNhIs2_qbumtrjLIbTEKy-YmmS1I_8zRtB3zPpOitxBTXtKx4hxHFD3TXtyUuXKR9g0OIWHYRVngsobGRFp4Mz7u02Cgh1IMLYizfB9UK5uIcNo0OrvH7VP8M5UMWQuSGxlLbGoz9oHcZR0pgGr4fjYZP5gIlKkrx4Y8bctk17BdLLN0BCY8WdG9SY67IE43JboZSB1zkNS5ErskJvuzP8A14e87zn_Ju9mf1HXT2vPO38Eb-nnvxVm4v4eihCwBTYdShVXW7A73j8ODyefSAOT_Vu9lyW7VFUqoakdUnXmpl1MbeKN-weeAyI4isCqEK93UbqAzMD6uaidFl_Br276oZ8zUcH2bDFjDxW8NkPkknG6C21WAmG6UnHcdkSpKaHY5naHb9j1j81Nhg0xm7ythldknP4Gq6INPpPJ1N07PqapoWF_OUsgzmsJhO55dFAdPNZZGdn28uSbk441ckJefpYjonaXqRpQlcEFpkwNKSXKawSNF5CjXlIhFiVydKb8-4MS1cXV5OF-RM0AKE8T_kIaQGS4t2668_S0RIfC5HWX74wUGcCT_zOFrWteG6CWVRlndrZzdn-soZMSnarUHnqeDGmt4sy62Aq_7XQs_9lMDJw91vcc5aLa5eCFp82fdqG63-DaVFZOURcNEKIOyuyH8CAAD__xlYEsg">