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

    <tr>
        <th>Summary</th>
        <td>
            Implement the `InterlockedCompareStore` 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 `InterlockedCompareStore` clang builtin,
- [ ] Link `InterlockedCompareStore` clang builtin with `hlsl_intrinsics.h`
- [ ] Add sema checks for `InterlockedCompareStore` to `CheckHLSLBuiltinFunctionCall` in `SemaChecking.cpp`
- [ ] Add codegen for `InterlockedCompareStore` to `EmitHLSLBuiltinExpr` in `CGBuiltin.cpp`
- [ ] Add codegen tests to `clang/test/CodeGenHLSL/builtins/InterlockedCompareStore.hlsl`
- [ ] Add sema tests to `clang/test/SemaHLSL/BuiltIns/InterlockedCompareStore-errors.hlsl`
- [ ] Create the `int_dx_InterlockedCompareStore` intrinsic in `IntrinsicsDirectX.td`
- [ ] Create the `DXILOpMapping` of `int_dx_InterlockedCompareStore` to  `79` in `DXIL.td`
- [ ] Create the  `InterlockedCompareStore.ll` and `InterlockedCompareStore_errors.ll` tests in `llvm/test/CodeGen/DirectX/`
- [ ] Create the `int_spv_InterlockedCompareStore` intrinsic in `IntrinsicsSPIRV.td`
- [ ] In SPIRVInstructionSelector.cpp create the `InterlockedCompareStore` lowering and map  it to `int_spv_InterlockedCompareStore` in `SPIRVInstructionSelector::selectIntrinsic`.
- [ ] Create SPIR-V backend test case in `llvm/test/CodeGen/SPIRV/hlsl-intrinsics/InterlockedCompareStore.ll`

## DirectX

| DXIL Opcode | DXIL OpName | Shader Model | Shader Stages |
| ----------- | ----------- | ------------ | ------------- |
| 79 | AtomicCompareExchange | 6.0 | () |

## SPIR-V

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

## Description:
  
Perform the following steps atomically with respect to any other atomic
accesses within *Scope* to the same location:  
1) load through *Pointer* to get an *Original Value*,  
2) get a *New Value* from *Value* only if *Original Value* equals
*Comparator*, and  
3) store the *New Value* back through *Pointer* only if *Original Value*
equaled *Comparator*.  
  
The instruction’s result is the *Original Value*.  
  
*Result Type* must be an [*integer type*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Integer) scalar.  
  
Use *Equal* for the memory semantics of this instruction when *Value*
and *Original Value* compare equal.  
  
Use *Unequal* for the memory semantics of this instruction when *Value*
and *Original Value* compare unequal. *Unequal* must not be set to
**Release** or **Acquire and Release**. In addition, *Unequal* cannot be
set to a stronger memory-order then *Equal*.  
  
The type of *Value* must be the same as *Result Type*. The type of the
value pointed to by *Pointer* must be the same as *Result Type*. This
type must also match the type of *Comparator*.  
  
*Memory* is a memory [*Scope*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Scope_-id-).

<table style="width:100%;">
<colgroup>
<col style="width: 10%" />
<col style="width: 10%" />
<col style="width: 10%" />
<col style="width: 10%" />
<col style="width: 10%" />
<col style="width: 10%" />
<col style="width: 10%" />
<col style="width: 10%" />
<col style="width: 10%" />
<col style="width: 10%" />
</colgroup>
<thead>
<tr>
<th>Word Count</th>
<th>Opcode</th>
<th>Results</th>
<th>Operands</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p>9</p></td>
<td class="tableblock halign-left valign-top"><p>230</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><em>&lt;id&gt;</em><br />
<em>Pointer</em></p></td>
<td class="tableblock halign-left valign-top"><p><a
href="#Scope_-id-"><em>Scope &lt;id&gt;</em></a><br />
<em>Memory</em></p></td>
<td class="tableblock halign-left valign-top"><p><a
href="#Memory_Semantics_-id-"><em>Memory Semantics
&lt;id&gt;</em></a><br />
<em>Equal</em></p></td>
<td class="tableblock halign-left valign-top"><p><a
href="#Memory_Semantics_-id-"><em>Memory Semantics
&lt;id&gt;</em></a><br />
<em>Unequal</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><em>&lt;id&gt;</em><br />
<em>Comparator</em></p></td>
</tr>
</tbody>
</table>



## Test Case(s)

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

RWStructuredBuffer<int64_t> buffer : register(u0);
[numthreads(1, 1, 1)]
export void fn(uint3 dispatchThreadID : SV_DispatchThreadID, int64_t p1, uint64_t p2) {
int index = dispatchThreadID.x;
    return InterlockedCompareStore(buffer[index], p1, p2);
}
```
 ### Example 2
```hlsl
//dxc InterlockedCompareStore_1_test.hlsl -T lib_6_8 -enable-16bit-types -O0

RWStructuredBuffer<int> buffer : register(u0);
[numthreads(1, 1, 1)]
export void fn(uint3 dispatchThreadID : SV_DispatchThreadID, int p1, uint p2) {
int index = dispatchThreadID.x;
    return InterlockedCompareStore(buffer[index], p1, p2);
}
```
## HLSL:

Atomically compares the destination to the comparison value. If they are identical, the destination is overwritten with the input value.

## Syntax

``` syntax
void InterlockedCompareStore(
  in R dest,
  in T compare_value,
  in T value
);
```

## Parameters

<dl> <dt>

*dest* \[in\]
</dt> <dd>

Type: **R**

The destination address.

</dd> <dt>

*compare\_value* \[in\]
</dt> <dd>

Type: **T**

The comparison value.

</dd> <dt>

*value* \[in\]
</dt> <dd>

Type: **T**

The input value.

</dd> </dl>

## Return value

This function does not return a value.

## Remarks

Atomically compares the value referenced by *dest* with *compare\_value* and stores *value* in the location referenced by *dest* if the values match. This operation can only be performed on **int** or **uint** typed resources and shared memory variables. There are two possible uses for this function. The first is when R is a shared memory variable type. In this case, the function performs the operation on the shared memory register referenced by *dest*. The second scenario is when R is a resource variable type. In this scenario, the function performs the operation on the resource location referenced by *dest*.

Interlocked operations do not imply any memory fence/barrier.

### Minimum Shader Model

This function is supported in the following shader models.



| Shader Model                                                                | Supported |
|-----------------------------------------------------------------------------|-----------|
| [Shader Model 5](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src//direct3dhlsl/d3d11-graphics-reference-sm5.md) and higher shader models | yes       |



 

This function is supported in the following types of shaders:



| Vertex | Hull | Domain | Geometry | Pixel | Compute |
|--------|------|--------|----------|-------|---------|
|  x     | x    |  x     |  x       | x     | x       |



 

## See also

<dl> <dt>

[Intrinsic Functions](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src//direct3dhlsl/dx-graphics-hlsl-intrinsic-functions.md)
</dt> <dt>

[Shader Model 5](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src//direct3dhlsl/d3d11-graphics-reference-sm5.md)
</dt> </dl>
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsOt1u27jST8PcEDZkKnbii1wodrwboN0WSba7dwEtji1-oUgtSSXx9_QHQ0qynNhOuttuC5wTFLU0HM7_kMOhuHNyrQEuyPiSjOcnvPaFsRcrbv_faHWyNGJzMaBkfEnJeE6vy0pBCdpTMkmutQerTP4AYmbKilu49cYCmSQ0V1yv6bKWyktN2Iwk2ZbIB6kfvmY-fZK-wAmFcupeam-ldjJ3w4JMkh3KmRDUQclpXkD-4OjK2DcYeYMIM0T_9cPth8vIcVHr3EujZ1wpxJIasW6h5AFT6vUwr6p93HMjYA363ZyvSul7jK-eK7tlOPulAb_FzYPzrqEYTEfYAmGELWZGwC-gkQdhi8aijrDFAdGGaOSDdj3CCK3TcAlSXx_jMgBrjXV7mc0scA_UF4BcpPb34vn-iCG7gGisdt0FyFxayP2fQy-O85j_ef3hU_WRV5XUayRpVu9j7Q1FxLPp1mdI6zjDI3ExjOHGtTiCdN_YLuJGj0TeSj2WrzxP2KKxA2GLt23tqse_Z-zbz9c3X_Zofq1pGLrWzts6pNUtKMi9sRjWNN8R4QhrZZ7ASr0O5il5Ran0TSi-S_CQwgckIWlG0syFt04lMkmG-6yFRAZf6JLnD6BF8ADNuYM3vBB4E7bAmB9sV7Ejqaia3MB_LCUspa0nI-xsRjHc6KcKFwLae_-Nl_H9tuACLP1oBKg-4NbzNTiENIQG2z_6xvtrwKBH6GwahjNvSpk36lw95wXX6yjSZJiEX8LOCZu2MzsVo3U7EBr_U7WXGhnPCTsvvK8c-o8tCFtYWEvn7Wb4UFijjRsau25sP0DjuwqCyWstVxLEqPXLsPClIiw9xIpNkcWOK8DlVlYYRXGIUpJkn8GujC1DOK-MUuYJI9Z5qBzlgTJXahN3NAsoTYhhrjfU-AJsg0SSjOc5OAcu4GJksew2NxUQluEMZODQy8rkvBEiSDBCoyrDBfWFNfW6wJmfjcQYa-auwVMeKH6yci01V_QLVzWSJmwWqDCkEvAQ7Td46jDoypoSgR3AaLWhcrWXHoW_aq5cMFsWjcox3yInzGTkliI3hzEf14EXHDHTDmhzjDdJssAdBH3JfBjYhv_uCkzcbkUgV4ycJ2Q6deifWnkqXSvUKw49MoRlNxH_bhOdVNbO0yUES48vCctQ6DVY6iPC9wjf68gimDPnituehL-7oMQVmiT40digWAmlsZuwv2svc4e7ny-k61uFPhWg-07HANViv8vzmDvR9a8F-F3DvyZCrRshdvkG12gT3OMAMzB6MDhRAXcxFTKKVVx4yvK_amkhROwOyhA3OC6EDMHDZi845VxHPiTJIifKqfPWaIyEqPfAWFySfaNf66AXMYpREwqTXua1IdYtBtzRV4E4pP3pvkBRHpECrUIeCRRquXmRWO8mLTG5A_UwhStnaMl9XoSpPakPJSBh2cdgB2QrHeVtOMSsaRe975Eugfb9QIoBYdNhs7ynM8-XCqjzGwUknRPGnqTwBUmzUZIQNibpJWGMpFcROzdqbU1d9QH7JtNRmMwYReH_h_wTIxO2eOVVXwAX2zfbGyDp1R_GCjoztfZxegD2xmOJtn8s5pQ7NBEs1-LA6A-G4pvdeds10tKIzV6TCTzhOxd9EdJtifUvLbiSaz1QsPL0MT57UzXZls7QG9PIqdrKI74JXZYmRymTJPvbtEk6gxJ_2UR5kl5KQdhkjU-RURxMZ0u7E4YB3F9xd5C_hxFIOuMkyQoLqzidsDQKcC06xL5Yb2lE2IK_Je6Psmy72_0Qq_a3nr5dA_wrzLpPsWY7_SF6Rd73t20pt0fFiEI7lFAD_BN9Y8X0X6NuW16-U-EflV6xSv3JhewVpe-S9PWOt7PHIQBlbwDJbsvgDpyns3B0OHeETeNgKIQjBiJdPfOyUkBHODpJ4r_QJ02aqlc85_RQb9CD86GrSgd3VMnl_eT-nA5Ao1CD0WQp_QBLckcHn5rO0s0ft-GIVVsQl_VqFRZEqf3k9N6T9IouA4xirRTLbTwfnNdJaIlcIo3xpa5LX1jgwhF2PsJTUPvfFMv2JIPnylhPH40UdKVxvtQ-pUK6Co8Kd2Hy9Txwuf1yP38BR2KNSLQKpOvulcUmEkoitadSC3imJJ2_Ij58jvJSSqkFX1t9yIqEnUetyfgy0Atnj1nDOnBsVD-b972035Hsbzly9A1d-ZO5sefCn819jevCPUbb78u2bbumrRAbQgKclzr03tqGXByXzmgaTthDeh1O3BvKLVApADcAPNzPXlGQjppHsE9Weg_NlZcPramq9g213T7pRnv-3IBaFahrocFHhw0UDCk1mTGSJTdBknhNt4XetereP8Z-w8vhCEaBWnv2LdkJ-plbXoIH67oDtlAYkvjgtysly6IUGSXjWXBd-J13K2tADrNENyuWxVnTpbmJP83QCwtzISw4tz3mI0mxV5BGcTKetbr_A6HuXgr1KkreIdF3EGNPZO1KgM-qJ0Tw5k1Mvc73SEs6umpuTKkw4EJrrclRvi92b6Dk9sEdz6_Yo7KwAgs6B9H0qNogiZfC-33FtYjt5NCz6sBSB8Jtx_wwbbnaSuBiNyu2uqjB43iYnHMdu89LoFXs-oOgRjfmxmX3RQ-x3sJw4RbUgjO1zcFFgQtuQbTNr0duJa70LrTvLIQVxD8ZWhnn5FIBrR24poPac0Ds9q2kdaFzHZqmN7Gttp9BkCV0MQOdPJQncX3qnNroF_2yNYGJ9tyl2-4uB60bJXSQG1Q6B82tNC9lbU1zSMx23leK2pF9MwaagO2toFtqjgoTYlyWldqEy5tG-RVSImyx5NZKsDtRj4H_UWpZ1uXOtdy-LEIN6wo3WxBt2Pauk-LsEmd361l3Jbhz5fcP_wK9TpDukm_wLf926W0vEsn4ckeV8b4O8Fr6ol4Oc1MStvgoc2ucWfm5CW3fJ6lTht5QZomLWYQKcA_eVANn86YMC5eqqQi1GVuIVIxGg7XlVSFzN-gCZODK8bAUWK9guhZyXYDd9UWw1wbc1no7zgn75te7O1Z5ZtXwctubyM7nX8B6rJvOZvTXWsWb3rkpudTh8RcwJXi7CS-f5XNzF4w1Qe3htV-7x32w3Zc-eOs7-tyFz3P70IM1jz2E3tNRu7XFD0C4aTheUYwvu7t82n7S4_6tKHrehtDujf-gdbuL0bRnD9_R4SdNgtdit_XCibhIxTSd8hO4GJ2x0WiSJKenJ8UFB5icnp2O8tF5fjad5rA8O02mCYPTZHq6OmUn8oIl7DQ5G01YkiTpdLhip0wk5-fT8ymwVQLkNIGSSzVU6rEcGrs-kc7VcDGdjtj5ieJLUC58ycZYCZ4v63Vo08wIY83nGiTNus9hmpH41dIrtPYWqR0wnqRZizuen9gLFGKwrNeOnCZKOu-2YnnpFVxsP5d7-_MWpNxF6Ult1cURJzffmAQBKmv-D3JP2CLYAr0bzfF4wf4TAAD__-WMBhI">