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

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

## DirectX

| DXIL Opcode | DXIL OpName | Shader Model | Shader Stages |
| ----------- | ----------- | ------------ | ------------- |
| 123 | QuadOp | 6.0 | ('library', 'compute', 'amplification', 'mesh', 'pixel', 'node') |

## SPIR-V

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

## Description:
  
Swap the *Value* of the [invocation](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Invocation) within the
[quad](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Quad) with another invocation in the quad using *Direction*.  
  
*Result Type* must be a scalar or vector of [*floating-point
type*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Floating), [*integer type*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Integer), or [*Boolean
type*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Boolean).  
  
*Execution* is a [*Scope*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Scope_-id-), but has no effect on the
behavior of this instruction. It must be **Subgroup**.  
  
The type of *Value* must be the same as *Result Type*.  
  
*Direction* is the kind of swap to perform.  
  
*Direction* must be a scalar of [*integer type*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Integer), whose
*Signedness* operand is 0.  
  
*Direction* must come from a [*constant
instruction*](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#ConstantInstruction).  
  
The value returned in *Result* is the value provided to *Value* by
another invocation in the same quad scope instance. The invocation
providing this value is determined according to *Direction*.  
  
A *Direction* of 0 indicates a horizontal swap;  
- Invocations with [quad indices](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#QuadIndex) of 0 and 1 swap values  
- Invocations with [quad indices](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#QuadIndex) of 2 and 3 swap values  
A *Direction* of 1 indicates a vertical swap;  
- Invocations with [quad indices](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#QuadIndex) of 0 and 2 swap values  
- Invocations with [quad indices](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#QuadIndex) of 1 and 3 swap values  
A *Direction* of 2 indicates a diagonal swap;  
- Invocations with [quad indices](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#QuadIndex) of 0 and 3 swap values  
- Invocations with [quad indices](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#QuadIndex) of 1 and 2 swap values  
  
*Direction* must be one of the above values.  
  
If an active invocation reads *Value* from an inactive invocation, the
resulting value is undefined.

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

<table style="width:100%;">
<colgroup>
<col style="width: 14%" />
<col style="width: 14%" />
<col style="width: 14%" />
<col style="width: 14%" />
<col style="width: 14%" />
<col style="width: 14%" />
<col style="width: 14%" />
</colgroup>
<thead>
<tr>
<th>Word Count</th>
<th>Opcode</th>
<th>Results</th>
<th>Operands</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p>6</p></td>
<td class="tableblock halign-left valign-top"><p>366</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><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>Direction</em></p></td>
</tr>
</tbody>
</table>



## Test Case(s)

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

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

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

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

Returns the specified local value which is read from the diagonally opposite lane in this quad.

## Syntax


``` syntax
<type> QuadReadAcrossDiagonal(
   <type> localValue
);
```



## Parameters

<dl> <dt>

*localValue* 
</dt> <dd>

The requested type.

</dd> </dl>

## Return value

The specified local value which is read from the diagonally opposite lane in this quad.

## Remarks

For more information on quads, refer to [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).

This function is supported from shader model 6.0 only in pixel and compute shaders.



 

## See also

<dl> <dt>

[Shader Model 6](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src//direct3dhlsl/shader-model-6-0.md)
</dt> </dl>
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWlFz46iy_jXkhZJLRrETP-RBduK9rprZ2TuZ3btvKSRaFjcItICcZH_9qQbZlid2MjtnfXYezlRqLEFDd3_dNN0g7pxca4AbMpmTye0F73xt7E3F7Z9Gq4vCiJebhJLJnJLJLV01rYIGtKdkmv5vx8Vn4CIvrXHuVvK10VyRaUpLxfWaFp1UXmrCFiTN93N8kPrxLwynT9LXSF8rpx6k9lZqJ0s3qsk0PZg4F4I6aDgtaygfHa2MfZuPN9i_QOr_-XD_YR4ZLjtdemn0gqtAJTVS3UPDA6XU61HZtseYl0bAGvS3Mr5rpB_wvXtu7Z7f4qe--T1mHpx3_YwBOMKW2EbYcmEE_AQaeRC27PF0hC2PSzZChE-C-gYfxKZnEoRevcEkAWuNdUd5LSxwD9TXgEyk9g_i-eE0ijtf6CFb7XzjVloo_e8jL95mcfv76sOn9iNvW6nXOKWpvomzNxTpxizbGwznepvhaZ8YRU_jWpymeeiBi6TRGpGzUpvmldEJW_YoELZ8H2jXbr4L6ftfVp9_O6L2StPQtdLO2y6sp3tQUHpj0aFpeSDBac7KPIGVeh2waXhLqfS9E36L2GHlnpCDZDnJchfedgqRaTo6BhVOkvxGC14-ghYBflpyB--YIPAmbInenuxj1-klqPpFgX8sIyyjWyvGtqsFRUejn1pc_3Tw_jNv4vt9zQVY-tEIUMOGe8_X4LClnyjZ_6PvvL9uSAYTjVkW-lGnT214nI7S8EvYNWFXShaW2xfCrgjDtqvSNG3nYd_Am1bJSpYcLbRvbsDV-7dWPoPav2oj4gyzrSw70KK5dk1ozU_tT9Z07c9G_6plZWyD0t4_8ZZMbgm7rr1vHboEWxK2tLCWztuX0WNtjTZuZOy6N2eC9nQtBCt2WlYSxHhr6lHtG0VYdpoZmyGTAwODK61sg-Khi1KS5kgclwfLf-OqA8JyDE-haTKXemN6sM4g_mo_O5uFDVhq5IxCT-Z_dFycgytitOVHuTa-Bkv3itIoA0X2tHMYFAjL4_IIkuajgFz4j7D8M7hOefrlpQ3YNZ3ztADKqSu54pYaSzchEISoP5kTllfKcC_1OmmN1J6kuY-Dz6HtsueFHoH-HASQ2sMaLD0j31Vk0bPFTCVwnhujgOvz6rxlwmaHprp7hrLrjUilo7wX6r40Z5MlzP2QSJH0UBSdpzV3VBsKVQWlp2br9AXUfCOjp_ha4sa7205GdOV3zoWysvy-K9a4_OPbQNUvNQTTBo8brOvtcHRvh3GcO_rKgw8hG_o9QoZDH6UWOLULscPQFizGnjcGvl4U1T_liU-1cRBFvMeKRGhwLgS9Fizu_tLR9D1VStMAraxpdi5UGu08D4t5YLQzabToma2GnGZfOcAGrU4t-M5qECGB2Jp6YMtI1VqzkQJESHkGDlO8kDQ_HSKDD4U46dDLg7tyXcKIogCDvSPNIwcMpsGxI1vpqAAPtpEoIS9LYyOJeSPk5l_3oTNhEiZwWwdc1bWx8k-jPVfBR0k2DyMTut9wXF_vxW0mjgZ3ru1mpQU8454TREUvG8fVE3BwP5B0LEiXvZLuKOrjA9Q3YL0sf2DM2Q-K-fivYM4OMBd9Qv_DYv5aqx9DuvEJj3hz-zIatrkxL8ymj55uEJxWFeWa8tLLzTAAUgtcuIPQGncPDKWvqHGbigmBDeEaQ-IuYHZaQIXxctRn95P5gre8kEr6l7NsNvvZQ1GxRYiw_EjxETsGUE7mH6ULWXQBlbFwDhF_je2hQgv8N2Adwj4eZX1y1IOVLTwvFFDnXxSQ7JYw9iSFr0mWj9OUsAnJ5oQxkt1F6tKomGINGo4NpuNLHMwYRY3-S3yMmLDlKzh9DVzs3-ygg2R3_2esoAvTaR-Hh8ZBfzydON4XMx13amDI9U70_lut-GYP3g5VLIx4OaqwoKXizkUkg5cWypSPtOZKrnWioPIYBfDZm7Z30myBWE4jp3Yvj_hb5s2mb89M0vy75ybZAhr8ZVPlSTaXgrDpGp8io9iZLQp74ESheViwHBCfAwSSLThJ89pCFYcTlkUBVmJHOBTrPY0IW_L_rLjDGnQocGj_C_Ies8W-pv5GS_xTThN33h9cyH3a8U2Cvg42B-EFG1D0viE9PBD8As7TBXdA2LXDvT10hp07UiDR3TNvWgV0jL3TNP6FS5W037zFc0lPXCV4cD7cwNDkC1WyeJg-XNMENMqUjKeF9AnW_Y4mn_rDaHhujfU0HJBd0koTdt0_t-N4ADsPmQXtC9sTnAm7DvSIeZqTq9uh9McVZN-j4Pj7Veyk3moYH8-tYPY9CrLvV3Cv39-vXq9auAzcHnN_DhPGUw1MGENKSJXBijRmz0-1LGvMoTEbjwk4Em9rKPVCTdsaJz1QxTXEUw7pwgnH6PDc_0V7_rxfUFvRqNt1ZItwpJXdnVYx5sgLRvJ0QB4kjsEK-W0xGGr_1UL-hVvegAfrdlmuUDgVPvj94mf5YG4WVnoMEoEoUIsd9ZcaqIU_OnAeRDie2-fQOET0Q_BZDXgEiaItIuz76c5tlc_QcPvYg7A0ljbGIj3WJrEMMzoMc1hhWajAhqOmyfzTBuxGwhNWdwf3WtNj5cpa-rorRqVpCFt-lGhWU_lbE2qUJ6kzRtiyUKZAbGKrAPfoTZs4W_ZrLgT6TISF2F_cucA5aZBzMk3SpALuOwsuqYxNtiOSMRs1WOuMtshKR6v-YwLE0XUtLkDowYyz0ibqM0qp0eoFUQzXXKEM7q_JelI3OvCx6J8H3g9AuXLmbW-bzP8RJL8GMWL12tW3fnshbjIxy2b8Am7GV2w8nqaXl7OL-kbMWFlclZfjmRDV1aSYZVDBLCuqqhJidj2-kDcsZZfp1XjK0vSKzUbT2bSq0oqVV1ABTKbkMoWGSzVSatNgTXshnevgZjYbX11dKF6AcuF7GMYa8Lzo1iFdWxDG-gtgkuW72_W-J34A8YpsWytvO4wnWb6lndxe2BsUIim6tSOXqZLOu71YXnoFN_uPbt69LseJ6fYDlovOqps37NpfWgf-rTX_D6UnbBmgQINGNDY37F8BAAD__9i9HMo">