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

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

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

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

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

Returns the specified local value read from the other lane in this quad in the X direction.

## Syntax

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

## Parameters

<dl> <dt>

*localValue* 
</dt> <dd>

The requested type.

</dd> </dl>

## Return value

The specified local value. If the source lane is inactive, the results are undefined.

## 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/eJzsWl9z4ygS_zTkhZJLRrEdP-RBduI9V83s7E1m9-YthUTL4oJAC8hJ9tNfNci2PHGSnb3NTR5ua2ojoOk_v24aGsydkxsNcEkmCzK5OuOdr429rLj9w2h1VhjxeJlQMllQMrmi66ZV0ID2lEzTf3ZcfAYu8tIa576SaUpLxfWGFp1UXmrCliTND5M_SH33Z-bRe-lrJKyVU7dSeyu1k6Ub1WSaHnHMhaAOGk7LGso7RytjnxHgDQ4skewfH24-LKKkVadLL41ecqWQSmqkuoGGB0qpN6OybU9JLY2ADehXJV430g8EXj-09iBo-VPf_ZoUD867nmOAirAV9hG2WhoBP4FGGYStegQdYatvVBohmM_i94IARKPnHrRdn-KegLXGupNClha4B-prQO5S-1vxcHsCsL2je3TWe8dfSQul_zry4mXeV1_XHz61H3nbSr1BlqZ6WaQ3FAnGLDs4BZm8LOmEw0cxfrgWJwZve3AiTYQ6ylJq2zxxJWGr3mDCVq-D6drt96F588v6828nLFxrGobW2nnbhXVxAwpKbyzGJy2PRJ8Qqcw9WKk3AYaGt5RK38fUi4qGNfeMZJLlJMtdaO1NINN0dAoVZJL8Rgte3oEWAWlacgevoB1kE7bC4E0O6ebEGlJ9cOM_lhGW0Z2nYt9sSTF86KcWVy4dtH_mTWzf1FyApR-NADXsuPF8Aw57ekbJ4T_6SvtpRzJgNGZZGEdjPrXhczpKw1_CLgibKVlYbh8JmxGGfbPSNG3n4dDBm1bJSpYcXXPobsDVh1YrH0AdmtqIyGG-02UPWvTTvgvd-Kn9yZqu_dnoX7WsjG1Q25t73pLJFWEXtfetw1hgK8JWFjbSefs4uqut0caNjN30fkzQka6F4L5Oy0qCGO98PKp9owjLnhfG5ijkyMHgSivbYHgYopSkORLHlcDy37jqgLAcs03omiyk3poerDdQf33gzuZhs5QaJaPSk8XvHRdvIRUx2smjXBtfg6UHQ2nUgaJ42jlMA4TlcXkETfNRQC78j7D8M7hOefrlsQ3YNZ3ztADKqSu54pYaS7chA4QkPlkQllfKcC_1JmmN1J6kuY-T38LaVS8LIwLjOSggtYcNWPqGctdRRC8WDxdB8sIYBVy_rc07IWx-7KrrByi73olUOsp7pW5K82a6BN63iRRJD0XReVpzR7WhUFVQemp2QV9AzbcyRoqvJW6u-31kRNd-H1yoK8tvumKDyz-2BqZ-qSG4NkTcYF3vpmN4O8zj3NEnEXwM2TDuETKceie1QNYu5A5DW7CYe16Y-HRRVD8qEu9r4yCqeIP1gtDgXEh6LVjc76Wj6WumlKYBWlnT7EOoNNp5HhbzwGlvZNGyF7YeSpp_EwBb9Dq14DurQYSTw87VA19GqtaarRQgwiFnEDDFI0nz51NkiKGQJx1GeQhXrksYUVRgsHekeZSAyTQEdhQrHRXgwTYSNeRlaWwkMS-k3PzbMQwmPH0J3NYBV3VtrPzDaM9ViFGSLcLMhB42HNfXZnGbibPBvdV2s9YCHnDPCapilI3j6gk4uHekHQvaZU-0O4n6-Aj1LVgvy3eMOXunmI-_B3N2hLmQfGP0O8b8qVXvQ7vxMxHx4vZlNOzOxrww2z57ukFyWleUa8pLL7fDBEgtcOGOUmvcPTCVPqHGbSoeCGxI15gS9wmz0wIqzJej_nQ_WSx5ywuppH98k83mwD0UFTuECMtPFB9xYADlZPFRunCKLqAyFt5CxV9jf6jQgvwtWIewj0dZfzjqwcqWnhcKqPOPCkh2RRi7l8LXJMvHaUrYhGQLwhjJriN1aVQ8Yg06Tk2m43OczBhFi_5PfIqYsNUTOH0NXBxadjBAsut_GSvo0nTax-mhczAebydOj8WTjntuYjjrPTP6X_Viyx61jk0sjHg8abCgpeLORSRDlBbKlHe05kpudKKg8pgF8Nubtg_SbIlYTqOk9qCP-Fv4ZtOXOZM0_8u8SbaEBv-yqfIkW0hB2HSDX1FQHMyWhT0KotA9LFiOiN8CBJItOUnz2kIVpxOWRQXWYk84VOs1iwhb8f-tusMadKhw6P8OfU_54lBT_0lP_KigiTvvO1fycOz4U4o-TTZH6QU7UPW-Iz2-EPwCztMld0DYhcO9PQyGnTtSINH1A29aBXSMo9M0_guPI2m_eYuHkn77TuDB-fCEQpMvVMnidnp7QRPQqEwynhbSJ1jwO5p86m-h4aE11tNwM3ZOK03YRf_djuPN6yIcKWhf0X4rkrCLQIgopzmZXQ31PW0S-y6Txn_dqE7qnU3x881Myr7LJPbXTTpY9Dca1BsT3uh2l9efA6d4V4HHwHDQo8pgnbm74eAinqaRJl5VKK4hXlJIR_vSIgx_pWK3wkbHN_mP2vOHvmunE3X73mwZbqiy6xNGxbPukpE8HdAFHWPSQSk7q4f27qX_wi1vwIN1-3OqUMgEP_xh-bJ8wJWFtRqXeSAK1GJP_aVGcH7vwHkQ4YLtcArGKaKfgt9qICNoFHGPEB_YnfTAiK5jTeRMZ0vowXf7yqYvZ2gsZhzlFp5WMTupDbd3PQgrY2ljLDoSq4tYSBkd_OmQqYUKbLgsmiw-bcFuJdxjfXb0MjU9VXBspK-7YlSahrDVR4meNJW_MqHKuJc6Y4StCmUKxCb2CnB33rSJs2W_okIgZSIss_7NzQXJSYOSk2mSJhVw31lwSWVsspuRjNmowWpltENWOlr1L_iInOtaXGXQx3XkSptozyilRqtHjOjwUBUK2f6hqyd1o6N0HyPzKNoBKFfOvBxtk8UPQfJbECNWT0N9F7dn4jIT82zOz-ByPGPj8TQ9Z7Oz-nLOJ-Mxm5ynGZtdzCdzVvKqms95BsV5OhbiTF6ylJ2ns_GUpeksnY5KNp6N04uyOC9hdl6V5DyFhks1UmrbYFV6Jp3r4HI-H88mZ4oXoFz4vQljDXhedJtw4FoSxvq3W5Ll-zfwfiT-BuEJ2a7a3Q0YT7J8Rzu5OrOXqERSdBtHzlMlnXcHtbz0Ci4PP2p5_m0bOdLdz0XOOqsuX3Bo_9AcBLfW_BtKT9gqYICejDBsL9l_AgAA__-2CtlQ">