Skip to content

[HLSL][DXIL][SPIRV] QuadReadAcrossDiagonal intrinsic support#188567

Merged
bogner merged 6 commits into
llvm:mainfrom
kcloudy0717:kcloudy0717/QuadReadAcrossDiagonal
Jun 16, 2026
Merged

[HLSL][DXIL][SPIRV] QuadReadAcrossDiagonal intrinsic support#188567
bogner merged 6 commits into
llvm:mainfrom
kcloudy0717:kcloudy0717/QuadReadAcrossDiagonal

Conversation

@kcloudy0717

Copy link
Copy Markdown
Contributor

This PR adds QuadReadAcrossDiagonal intrinsic support in HLSL with codegen for both DirectX and SPIRV backends. Resolves #99177.

  • 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

@llvmbot llvmbot added backend:X86 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:headers Headers provided by Clang, e.g. for intrinsics clang:codegen IR generation bugs: mangling, exceptions, etc. backend:DirectX HLSL HLSL Language Support backend:SPIR-V llvm:ir labels Mar 25, 2026
@kcloudy0717

Copy link
Copy Markdown
Contributor Author

Pinging @bob80905 and @farzonl for review.

@llvmbot

llvmbot commented Mar 25, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-clang-codegen
@llvm/pr-subscribers-backend-x86

@llvm/pr-subscribers-backend-directx

Author: Kai (kcloudy0717)

Changes

This PR adds QuadReadAcrossDiagonal intrinsic support in HLSL with codegen for both DirectX and SPIRV backends. Resolves #99177.

  • 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

Patch is 32.08 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/188567.diff

16 Files Affected:

  • (modified) clang/include/clang/Basic/Builtins.td (+6)
  • (modified) clang/lib/CodeGen/CGHLSLBuiltins.cpp (+8)
  • (modified) clang/lib/CodeGen/CGHLSLRuntime.h (+2)
  • (modified) clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h (+99)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+2-1)
  • (added) clang/test/CodeGenHLSL/builtins/QuadReadAcrossDiagonal.hlsl (+171)
  • (added) clang/test/SemaHLSL/BuiltIns/QuadReadAcrossDiagonal-errors.hlsl (+28)
  • (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+1)
  • (modified) llvm/include/llvm/IR/IntrinsicsSPIRV.td (+1)
  • (modified) llvm/lib/Target/DirectX/DXIL.td (+4)
  • (modified) llvm/lib/Target/DirectX/DXILShaderFlags.cpp (+1)
  • (modified) llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp (+1)
  • (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (+3)
  • (added) llvm/test/CodeGen/DirectX/QuadReadAcrossDiagonal.ll (+87)
  • (modified) llvm/test/CodeGen/DirectX/ShaderFlags/wave-ops.ll (+7)
  • (added) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadReadAcrossDiagonal.ll (+44)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index b8621a0dff1f0..bde0820570ec9 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5288,6 +5288,12 @@ def HLSLQuadReadAcrossY : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLQuadReadAcrossDiagonal : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_quad_read_across_diagonal"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 def HLSLClamp : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_clamp"];
   let Attributes = [NoThrow, Const, CustomTypeChecking];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 29c41893bdbc4..3e15ed05ad645 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -1455,6 +1455,14 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
                                &CGM.getModule(), ID, {OpExpr->getType()}),
                            ArrayRef{OpExpr}, "hlsl.quad.read.across.y");
   }
+  case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
+    Value *OpExpr = EmitScalarExpr(E->getArg(0));
+    Intrinsic::ID ID =
+        CGM.getHLSLRuntime().getQuadReadAcrossDiagonalIntrinsic();
+    return EmitRuntimeCall(Intrinsic::getOrInsertDeclaration(
+                               &CGM.getModule(), ID, {OpExpr->getType()}),
+                           ArrayRef{OpExpr}, "hlsl.quad.read.across.diagonal");
+  }
   case Builtin::BI__builtin_hlsl_elementwise_sign: {
     auto *Arg0 = E->getArg(0);
     Value *Op0 = EmitScalarExpr(Arg0);
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index c3f3bde241b65..0c159fd1f61fc 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -160,6 +160,8 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(QuadReadAcrossX, quad_read_across_x)
   GENERATE_HLSL_INTRINSIC_FUNCTION(QuadReadAcrossY, quad_read_across_y)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(QuadReadAcrossDiagonal,
+                                   quad_read_across_diagonal)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow)
diff --git a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
index 62cbdb0e3ba07..9d723e49b7555 100644
--- a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
@@ -3740,6 +3740,105 @@ __attribute__((convergent)) double3 QuadReadAcrossY(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_y)
 __attribute__((convergent)) double4 QuadReadAcrossY(double4);
 
+//===----------------------------------------------------------------------===//
+// QuadReadAcrossDiagonal builtins
+//===----------------------------------------------------------------------===//
+
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) half QuadReadAcrossDiagonal(half);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) half2 QuadReadAcrossDiagonal(half2);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) half3 QuadReadAcrossDiagonal(half3);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) half4 QuadReadAcrossDiagonal(half4);
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int16_t QuadReadAcrossDiagonal(int16_t);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int16_t2 QuadReadAcrossDiagonal(int16_t2);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int16_t3 QuadReadAcrossDiagonal(int16_t3);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int16_t4 QuadReadAcrossDiagonal(int16_t4);
+
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint16_t QuadReadAcrossDiagonal(uint16_t);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint16_t2 QuadReadAcrossDiagonal(uint16_t2);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint16_t3 QuadReadAcrossDiagonal(uint16_t3);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint16_t4 QuadReadAcrossDiagonal(uint16_t4);
+#endif
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int QuadReadAcrossDiagonal(int);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int2 QuadReadAcrossDiagonal(int2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int3 QuadReadAcrossDiagonal(int3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int4 QuadReadAcrossDiagonal(int4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint QuadReadAcrossDiagonal(uint);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint2 QuadReadAcrossDiagonal(uint2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint3 QuadReadAcrossDiagonal(uint3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint4 QuadReadAcrossDiagonal(uint4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int64_t QuadReadAcrossDiagonal(int64_t);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int64_t2 QuadReadAcrossDiagonal(int64_t2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int64_t3 QuadReadAcrossDiagonal(int64_t3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int64_t4 QuadReadAcrossDiagonal(int64_t4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint64_t QuadReadAcrossDiagonal(uint64_t);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint64_t2 QuadReadAcrossDiagonal(uint64_t2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint64_t3 QuadReadAcrossDiagonal(uint64_t3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint64_t4 QuadReadAcrossDiagonal(uint64_t4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) float QuadReadAcrossDiagonal(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) float2 QuadReadAcrossDiagonal(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) float3 QuadReadAcrossDiagonal(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) float4 QuadReadAcrossDiagonal(float4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) double QuadReadAcrossDiagonal(double);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) double2 QuadReadAcrossDiagonal(double2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) double3 QuadReadAcrossDiagonal(double3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) double4 QuadReadAcrossDiagonal(double4);
+
 //===----------------------------------------------------------------------===//
 // sign builtins
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index aebe284b2399a..490b56b743cdb 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -4308,7 +4308,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     break;
   }
   case Builtin::BI__builtin_hlsl_quad_read_across_x:
-  case Builtin::BI__builtin_hlsl_quad_read_across_y: {
+  case Builtin::BI__builtin_hlsl_quad_read_across_y:
+  case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
     if (SemaRef.checkArgCount(TheCall, 1))
       return true;
 
diff --git a/clang/test/CodeGenHLSL/builtins/QuadReadAcrossDiagonal.hlsl b/clang/test/CodeGenHLSL/builtins/QuadReadAcrossDiagonal.hlsl
new file mode 100644
index 0000000000000..f89be574e8e75
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/QuadReadAcrossDiagonal.hlsl
@@ -0,0 +1,171 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-compute %s -fnative-half-type -fnative-int16-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN:   --check-prefixes=CHECK,CHECK-DXIL,CHECK-NATIVE_HALF
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-compute %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL,CHECK-NO_HALF
+
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   spirv-unknown-vulkan-compute %s -fnative-half-type -fnative-int16-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN:   --check-prefixes=CHECK,CHECK-SPIRV,CHECK-NATIVE_HALF
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV,CHECK-NO_HALF
+
+// Capture the expected interchange format so not every check needs to be duplicated
+// CHECK-DXIL: %[[RET:.*]] = call [[CC:]]i32 @llvm.[[ICF:dx]].quad.read.across.diagonal.i32(i32 %[[#]])
+// CHECK-SPIRV: %[[RET:.*]] = call [[CC:spir_func ]]i32 @llvm.[[ICF:spv]].quad.read.across.diagonal.i32(i32 %[[#]])
+// CHECK: ret i32 %[[RET]]
+int test_int(int expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<2 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v2i32(<2 x i32> %[[#]])
+// CHECK: ret <2 x i32> %[[RET]]
+int2 test_int2(int2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<3 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v3i32(<3 x i32> %[[#]])
+// CHECK: ret <3 x i32> %[[RET]]
+int3 test_int3(int3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<4 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v4i32(<4 x i32> %[[#]])
+// CHECK: ret <4 x i32> %[[RET]]
+int4 test_int4(int4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]i32 @llvm.[[ICF]].quad.read.across.diagonal.i32(i32 %[[#]])
+// CHECK: ret i32 %[[RET]]
+uint test_uint(uint expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<2 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v2i32(<2 x i32> %[[#]])
+// CHECK: ret <2 x i32> %[[RET]]
+uint2 test_uint2(uint2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<3 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v3i32(<3 x i32> %[[#]])
+// CHECK: ret <3 x i32> %[[RET]]
+uint3 test_uint3(uint3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<4 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v4i32(<4 x i32> %[[#]])
+// CHECK: ret <4 x i32> %[[RET]]
+uint4 test_uint4(uint4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]i64 @llvm.[[ICF]].quad.read.across.diagonal.i64(i64 %[[#]])
+// CHECK: ret i64 %[[RET]]
+int64_t test_int64_t(int64_t expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<2 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v2i64(<2 x i64> %[[#]])
+// CHECK: ret <2 x i64> %[[RET]]
+int64_t2 test_int64_t2(int64_t2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<3 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v3i64(<3 x i64> %[[#]])
+// CHECK: ret <3 x i64> %[[RET]]
+int64_t3 test_int64_t3(int64_t3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<4 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v4i64(<4 x i64> %[[#]])
+// CHECK: ret <4 x i64> %[[RET]]
+int64_t4 test_int64_t4(int64_t4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]i64 @llvm.[[ICF]].quad.read.across.diagonal.i64(i64 %[[#]])
+// CHECK: ret i64 %[[RET]]
+uint64_t test_uint64_t(uint64_t expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<2 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v2i64(<2 x i64> %[[#]])
+// CHECK: ret <2 x i64> %[[RET]]
+uint64_t2 test_uint64_t2(uint64_t2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<3 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v3i64(<3 x i64> %[[#]])
+// CHECK: ret <3 x i64> %[[RET]]
+uint64_t3 test_uint64_t3(uint64_t3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<4 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v4i64(<4 x i64> %[[#]])
+// CHECK: ret <4 x i64> %[[RET]]
+uint64_t4 test_uint64_t4(uint64_t4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]float @llvm.[[ICF]].quad.read.across.diagonal.f32(float %[[#]])
+// CHECK: ret float %[[RET]]
+float test_float(float expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<2 x float> @llvm.[[ICF]].quad.read.across.diagonal.v2f32(<2 x float> %[[#]])
+// CHECK: ret <2 x float> %[[RET]]
+float2 test_float2(float2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<3 x float> @llvm.[[ICF]].quad.read.across.diagonal.v3f32(<3 x float> %[[#]])
+// CHECK: ret <3 x float> %[[RET]]
+float3 test_float3(float3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<4 x float> @llvm.[[ICF]].quad.read.across.diagonal.v4f32(<4 x float> %[[#]])
+// CHECK: ret <4 x float> %[[RET]]
+float4 test_float4(float4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]double @llvm.[[ICF]].quad.read.across.diagonal.f64(double %[[#]])
+// CHECK: ret double %[[RET]]
+double test_double(double expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<2 x double> @llvm.[[ICF]].quad.read.across.diagonal.v2f64(<2 x double> %[[#]])
+// CHECK: ret <2 x double> %[[RET]]
+double2 test_double2(double2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<3 x double> @llvm.[[ICF]].quad.read.across.diagonal.v3f64(<3 x double> %[[#]])
+// CHECK: ret <3 x double> %[[RET]]
+double3 test_double3(double3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<4 x double> @llvm.[[ICF]].quad.read.across.diagonal.v4f64(<4 x double> %[[#]])
+// CHECK: ret <4 x double> %[[RET]]
+double4 test_double4(double4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]half @llvm.[[ICF]].quad.read.across.diagonal.f16(half %[[#]])
+// CHECK-NATIVE_HALF: ret half %[[RET]]
+// CHECK-NO_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]float @llvm.[[ICF]].quad.read.across.diagonal.f32(float %[[#]])
+// CHECK-NO_HALF: ret float %[[RET]]
+half test_half(half expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<2 x half> @llvm.[[ICF]].quad.read.across.diagonal.v2f16(<2 x half> %[[#]])
+// CHECK-NATIVE_HALF: ret <2 x half> %[[RET]]
+// CHECK-NO_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<2 x float> @llvm.[[ICF]].quad.read.across.diagonal.v2f32(<2 x float> %[[#]])
+// CHECK-NO_HALF: ret <2 x float> %[[RET]]
+half2 test_half2(half2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<3 x half> @llvm.[[ICF]].quad.read.across.diagonal.v3f16(<3 x half> %[[#]])
+// CHECK-NATIVE_HALF: ret <3 x half> %[[RET]]
+// CHECK-NO_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<3 x float> @llvm.[[ICF]].quad.read.across.diagonal.v3f32(<3 x float> %[[#]])
+// CHECK-NO_HALF: ret <3 x float> %[[RET]]
+half3 test_half3(half3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<4 x half> @llvm.[[ICF]].quad.read.across.diagonal.v4f16(<4 x half> %[[#]])
+// CHECK-NATIVE_HALF: ret <4 x half> %[[RET]]
+// CHECK-NO_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<4 x float> @llvm.[[ICF]].quad.read.across.diagonal.v4f32(<4 x float> %[[#]])
+// CHECK-NO_HALF: ret <4 x float> %[[RET]]
+half4 test_half4(half4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+#ifdef __HLSL_ENABLE_16_BIT
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]i16 @llvm.[[ICF]].quad.read.across.diagonal.i16(i16 %[[#]])
+// CHECK-NATIVE_HALF: ret i16 %[[RET]]
+int16_t test_int16_t(int16_t expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<2 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v2i16(<2 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <2 x i16> %[[RET]]
+int16_t2 test_int16_t2(int16_t2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<3 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v3i16(<3 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <3 x i16> %[[RET]]
+int16_t3 test_int16_t3(int16_t3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<4 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v4i16(<4 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <4 x i16> %[[RET]]
+int16_t4 test_int16_t4(int16_t4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]i16 @llvm.[[ICF]].quad.read.across.diagonal.i16(i16 %[[#]])
+// CHECK-NATIVE_HALF: ret i16 %[[RET]]
+uint16_t test_uint16_t(uint16_t expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<2 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v2i16(<2 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <2 x i16> %[[RET]]
+uint16_t2 test_uint16_t2(uint16_t2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<3 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v3i16(<3 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <3 x i16> %[[RET]]
+uint16_t3 test_uint16_t3(uint16_t3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<4 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v4i16(<4 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <4 x i16> %[[RET]]
+uint16_t4 test_uint16_t4(uint16_t4 expr) { return QuadReadAcrossDiagonal(expr); }
+#endif
diff --git a/clang/test/SemaHLSL/BuiltIns/QuadReadAcrossDiagonal-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/QuadReadAcrossDiagonal-errors.hlsl
new file mode 100644
index 0000000000000..322eacd7ca798
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/QuadReadAcrossDiagonal-errors.hlsl
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -finclude-defau...
[truncated]

@llvmbot

llvmbot commented Mar 25, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-backend-spir-v

Author: Kai (kcloudy0717)

Changes

This PR adds QuadReadAcrossDiagonal intrinsic support in HLSL with codegen for both DirectX and SPIRV backends. Resolves #99177.

  • 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

Patch is 32.08 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/188567.diff

16 Files Affected:

  • (modified) clang/include/clang/Basic/Builtins.td (+6)
  • (modified) clang/lib/CodeGen/CGHLSLBuiltins.cpp (+8)
  • (modified) clang/lib/CodeGen/CGHLSLRuntime.h (+2)
  • (modified) clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h (+99)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+2-1)
  • (added) clang/test/CodeGenHLSL/builtins/QuadReadAcrossDiagonal.hlsl (+171)
  • (added) clang/test/SemaHLSL/BuiltIns/QuadReadAcrossDiagonal-errors.hlsl (+28)
  • (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+1)
  • (modified) llvm/include/llvm/IR/IntrinsicsSPIRV.td (+1)
  • (modified) llvm/lib/Target/DirectX/DXIL.td (+4)
  • (modified) llvm/lib/Target/DirectX/DXILShaderFlags.cpp (+1)
  • (modified) llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp (+1)
  • (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (+3)
  • (added) llvm/test/CodeGen/DirectX/QuadReadAcrossDiagonal.ll (+87)
  • (modified) llvm/test/CodeGen/DirectX/ShaderFlags/wave-ops.ll (+7)
  • (added) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadReadAcrossDiagonal.ll (+44)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index b8621a0dff1f0..bde0820570ec9 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5288,6 +5288,12 @@ def HLSLQuadReadAcrossY : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLQuadReadAcrossDiagonal : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_quad_read_across_diagonal"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 def HLSLClamp : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_clamp"];
   let Attributes = [NoThrow, Const, CustomTypeChecking];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 29c41893bdbc4..3e15ed05ad645 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -1455,6 +1455,14 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
                                &CGM.getModule(), ID, {OpExpr->getType()}),
                            ArrayRef{OpExpr}, "hlsl.quad.read.across.y");
   }
+  case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
+    Value *OpExpr = EmitScalarExpr(E->getArg(0));
+    Intrinsic::ID ID =
+        CGM.getHLSLRuntime().getQuadReadAcrossDiagonalIntrinsic();
+    return EmitRuntimeCall(Intrinsic::getOrInsertDeclaration(
+                               &CGM.getModule(), ID, {OpExpr->getType()}),
+                           ArrayRef{OpExpr}, "hlsl.quad.read.across.diagonal");
+  }
   case Builtin::BI__builtin_hlsl_elementwise_sign: {
     auto *Arg0 = E->getArg(0);
     Value *Op0 = EmitScalarExpr(Arg0);
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index c3f3bde241b65..0c159fd1f61fc 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -160,6 +160,8 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(QuadReadAcrossX, quad_read_across_x)
   GENERATE_HLSL_INTRINSIC_FUNCTION(QuadReadAcrossY, quad_read_across_y)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(QuadReadAcrossDiagonal,
+                                   quad_read_across_diagonal)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow)
diff --git a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
index 62cbdb0e3ba07..9d723e49b7555 100644
--- a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
@@ -3740,6 +3740,105 @@ __attribute__((convergent)) double3 QuadReadAcrossY(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_y)
 __attribute__((convergent)) double4 QuadReadAcrossY(double4);
 
+//===----------------------------------------------------------------------===//
+// QuadReadAcrossDiagonal builtins
+//===----------------------------------------------------------------------===//
+
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) half QuadReadAcrossDiagonal(half);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) half2 QuadReadAcrossDiagonal(half2);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) half3 QuadReadAcrossDiagonal(half3);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) half4 QuadReadAcrossDiagonal(half4);
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int16_t QuadReadAcrossDiagonal(int16_t);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int16_t2 QuadReadAcrossDiagonal(int16_t2);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int16_t3 QuadReadAcrossDiagonal(int16_t3);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int16_t4 QuadReadAcrossDiagonal(int16_t4);
+
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint16_t QuadReadAcrossDiagonal(uint16_t);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint16_t2 QuadReadAcrossDiagonal(uint16_t2);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint16_t3 QuadReadAcrossDiagonal(uint16_t3);
+_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint16_t4 QuadReadAcrossDiagonal(uint16_t4);
+#endif
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int QuadReadAcrossDiagonal(int);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int2 QuadReadAcrossDiagonal(int2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int3 QuadReadAcrossDiagonal(int3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int4 QuadReadAcrossDiagonal(int4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint QuadReadAcrossDiagonal(uint);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint2 QuadReadAcrossDiagonal(uint2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint3 QuadReadAcrossDiagonal(uint3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint4 QuadReadAcrossDiagonal(uint4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int64_t QuadReadAcrossDiagonal(int64_t);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int64_t2 QuadReadAcrossDiagonal(int64_t2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int64_t3 QuadReadAcrossDiagonal(int64_t3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) int64_t4 QuadReadAcrossDiagonal(int64_t4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint64_t QuadReadAcrossDiagonal(uint64_t);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint64_t2 QuadReadAcrossDiagonal(uint64_t2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint64_t3 QuadReadAcrossDiagonal(uint64_t3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) uint64_t4 QuadReadAcrossDiagonal(uint64_t4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) float QuadReadAcrossDiagonal(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) float2 QuadReadAcrossDiagonal(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) float3 QuadReadAcrossDiagonal(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) float4 QuadReadAcrossDiagonal(float4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) double QuadReadAcrossDiagonal(double);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) double2 QuadReadAcrossDiagonal(double2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) double3 QuadReadAcrossDiagonal(double3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_quad_read_across_diagonal)
+__attribute__((convergent)) double4 QuadReadAcrossDiagonal(double4);
+
 //===----------------------------------------------------------------------===//
 // sign builtins
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index aebe284b2399a..490b56b743cdb 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -4308,7 +4308,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     break;
   }
   case Builtin::BI__builtin_hlsl_quad_read_across_x:
-  case Builtin::BI__builtin_hlsl_quad_read_across_y: {
+  case Builtin::BI__builtin_hlsl_quad_read_across_y:
+  case Builtin::BI__builtin_hlsl_quad_read_across_diagonal: {
     if (SemaRef.checkArgCount(TheCall, 1))
       return true;
 
diff --git a/clang/test/CodeGenHLSL/builtins/QuadReadAcrossDiagonal.hlsl b/clang/test/CodeGenHLSL/builtins/QuadReadAcrossDiagonal.hlsl
new file mode 100644
index 0000000000000..f89be574e8e75
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/QuadReadAcrossDiagonal.hlsl
@@ -0,0 +1,171 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-compute %s -fnative-half-type -fnative-int16-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN:   --check-prefixes=CHECK,CHECK-DXIL,CHECK-NATIVE_HALF
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-compute %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL,CHECK-NO_HALF
+
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   spirv-unknown-vulkan-compute %s -fnative-half-type -fnative-int16-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN:   --check-prefixes=CHECK,CHECK-SPIRV,CHECK-NATIVE_HALF
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV,CHECK-NO_HALF
+
+// Capture the expected interchange format so not every check needs to be duplicated
+// CHECK-DXIL: %[[RET:.*]] = call [[CC:]]i32 @llvm.[[ICF:dx]].quad.read.across.diagonal.i32(i32 %[[#]])
+// CHECK-SPIRV: %[[RET:.*]] = call [[CC:spir_func ]]i32 @llvm.[[ICF:spv]].quad.read.across.diagonal.i32(i32 %[[#]])
+// CHECK: ret i32 %[[RET]]
+int test_int(int expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<2 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v2i32(<2 x i32> %[[#]])
+// CHECK: ret <2 x i32> %[[RET]]
+int2 test_int2(int2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<3 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v3i32(<3 x i32> %[[#]])
+// CHECK: ret <3 x i32> %[[RET]]
+int3 test_int3(int3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<4 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v4i32(<4 x i32> %[[#]])
+// CHECK: ret <4 x i32> %[[RET]]
+int4 test_int4(int4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]i32 @llvm.[[ICF]].quad.read.across.diagonal.i32(i32 %[[#]])
+// CHECK: ret i32 %[[RET]]
+uint test_uint(uint expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<2 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v2i32(<2 x i32> %[[#]])
+// CHECK: ret <2 x i32> %[[RET]]
+uint2 test_uint2(uint2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<3 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v3i32(<3 x i32> %[[#]])
+// CHECK: ret <3 x i32> %[[RET]]
+uint3 test_uint3(uint3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<4 x i32> @llvm.[[ICF]].quad.read.across.diagonal.v4i32(<4 x i32> %[[#]])
+// CHECK: ret <4 x i32> %[[RET]]
+uint4 test_uint4(uint4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]i64 @llvm.[[ICF]].quad.read.across.diagonal.i64(i64 %[[#]])
+// CHECK: ret i64 %[[RET]]
+int64_t test_int64_t(int64_t expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<2 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v2i64(<2 x i64> %[[#]])
+// CHECK: ret <2 x i64> %[[RET]]
+int64_t2 test_int64_t2(int64_t2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<3 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v3i64(<3 x i64> %[[#]])
+// CHECK: ret <3 x i64> %[[RET]]
+int64_t3 test_int64_t3(int64_t3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<4 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v4i64(<4 x i64> %[[#]])
+// CHECK: ret <4 x i64> %[[RET]]
+int64_t4 test_int64_t4(int64_t4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]i64 @llvm.[[ICF]].quad.read.across.diagonal.i64(i64 %[[#]])
+// CHECK: ret i64 %[[RET]]
+uint64_t test_uint64_t(uint64_t expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<2 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v2i64(<2 x i64> %[[#]])
+// CHECK: ret <2 x i64> %[[RET]]
+uint64_t2 test_uint64_t2(uint64_t2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<3 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v3i64(<3 x i64> %[[#]])
+// CHECK: ret <3 x i64> %[[RET]]
+uint64_t3 test_uint64_t3(uint64_t3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call [[CC]]<4 x i64> @llvm.[[ICF]].quad.read.across.diagonal.v4i64(<4 x i64> %[[#]])
+// CHECK: ret <4 x i64> %[[RET]]
+uint64_t4 test_uint64_t4(uint64_t4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]float @llvm.[[ICF]].quad.read.across.diagonal.f32(float %[[#]])
+// CHECK: ret float %[[RET]]
+float test_float(float expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<2 x float> @llvm.[[ICF]].quad.read.across.diagonal.v2f32(<2 x float> %[[#]])
+// CHECK: ret <2 x float> %[[RET]]
+float2 test_float2(float2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<3 x float> @llvm.[[ICF]].quad.read.across.diagonal.v3f32(<3 x float> %[[#]])
+// CHECK: ret <3 x float> %[[RET]]
+float3 test_float3(float3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<4 x float> @llvm.[[ICF]].quad.read.across.diagonal.v4f32(<4 x float> %[[#]])
+// CHECK: ret <4 x float> %[[RET]]
+float4 test_float4(float4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]double @llvm.[[ICF]].quad.read.across.diagonal.f64(double %[[#]])
+// CHECK: ret double %[[RET]]
+double test_double(double expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<2 x double> @llvm.[[ICF]].quad.read.across.diagonal.v2f64(<2 x double> %[[#]])
+// CHECK: ret <2 x double> %[[RET]]
+double2 test_double2(double2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<3 x double> @llvm.[[ICF]].quad.read.across.diagonal.v3f64(<3 x double> %[[#]])
+// CHECK: ret <3 x double> %[[RET]]
+double3 test_double3(double3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<4 x double> @llvm.[[ICF]].quad.read.across.diagonal.v4f64(<4 x double> %[[#]])
+// CHECK: ret <4 x double> %[[RET]]
+double4 test_double4(double4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]half @llvm.[[ICF]].quad.read.across.diagonal.f16(half %[[#]])
+// CHECK-NATIVE_HALF: ret half %[[RET]]
+// CHECK-NO_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]float @llvm.[[ICF]].quad.read.across.diagonal.f32(float %[[#]])
+// CHECK-NO_HALF: ret float %[[RET]]
+half test_half(half expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<2 x half> @llvm.[[ICF]].quad.read.across.diagonal.v2f16(<2 x half> %[[#]])
+// CHECK-NATIVE_HALF: ret <2 x half> %[[RET]]
+// CHECK-NO_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<2 x float> @llvm.[[ICF]].quad.read.across.diagonal.v2f32(<2 x float> %[[#]])
+// CHECK-NO_HALF: ret <2 x float> %[[RET]]
+half2 test_half2(half2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<3 x half> @llvm.[[ICF]].quad.read.across.diagonal.v3f16(<3 x half> %[[#]])
+// CHECK-NATIVE_HALF: ret <3 x half> %[[RET]]
+// CHECK-NO_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<3 x float> @llvm.[[ICF]].quad.read.across.diagonal.v3f32(<3 x float> %[[#]])
+// CHECK-NO_HALF: ret <3 x float> %[[RET]]
+half3 test_half3(half3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<4 x half> @llvm.[[ICF]].quad.read.across.diagonal.v4f16(<4 x half> %[[#]])
+// CHECK-NATIVE_HALF: ret <4 x half> %[[RET]]
+// CHECK-NO_HALF: %[[RET:.*]] = call reassoc nnan ninf nsz arcp afn [[CC]]<4 x float> @llvm.[[ICF]].quad.read.across.diagonal.v4f32(<4 x float> %[[#]])
+// CHECK-NO_HALF: ret <4 x float> %[[RET]]
+half4 test_half4(half4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+#ifdef __HLSL_ENABLE_16_BIT
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]i16 @llvm.[[ICF]].quad.read.across.diagonal.i16(i16 %[[#]])
+// CHECK-NATIVE_HALF: ret i16 %[[RET]]
+int16_t test_int16_t(int16_t expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<2 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v2i16(<2 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <2 x i16> %[[RET]]
+int16_t2 test_int16_t2(int16_t2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<3 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v3i16(<3 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <3 x i16> %[[RET]]
+int16_t3 test_int16_t3(int16_t3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<4 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v4i16(<4 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <4 x i16> %[[RET]]
+int16_t4 test_int16_t4(int16_t4 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]i16 @llvm.[[ICF]].quad.read.across.diagonal.i16(i16 %[[#]])
+// CHECK-NATIVE_HALF: ret i16 %[[RET]]
+uint16_t test_uint16_t(uint16_t expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<2 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v2i16(<2 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <2 x i16> %[[RET]]
+uint16_t2 test_uint16_t2(uint16_t2 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<3 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v3i16(<3 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <3 x i16> %[[RET]]
+uint16_t3 test_uint16_t3(uint16_t3 expr) { return QuadReadAcrossDiagonal(expr); }
+
+// CHECK-NATIVE_HALF: %[[RET:.*]] = call [[CC]]<4 x i16> @llvm.[[ICF]].quad.read.across.diagonal.v4i16(<4 x i16> %[[#]])
+// CHECK-NATIVE_HALF: ret <4 x i16> %[[RET]]
+uint16_t4 test_uint16_t4(uint16_t4 expr) { return QuadReadAcrossDiagonal(expr); }
+#endif
diff --git a/clang/test/SemaHLSL/BuiltIns/QuadReadAcrossDiagonal-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/QuadReadAcrossDiagonal-errors.hlsl
new file mode 100644
index 0000000000000..322eacd7ca798
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/QuadReadAcrossDiagonal-errors.hlsl
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -finclude-defau...
[truncated]

Comment thread llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadReadAcrossDiagonal.ll Outdated

@s-perron s-perron left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SPIR-V code looks good. Just update the test to target vulkan 1.3 and use the target env when calling spirv-val.

@kcloudy0717 kcloudy0717 force-pushed the kcloudy0717/QuadReadAcrossDiagonal branch 3 times, most recently from 636dd64 to 7defcbe Compare March 26, 2026 14:46

@bob80905 bob80905 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bob80905

Copy link
Copy Markdown
Contributor

The SPIR-V code looks good. Just update the test to target vulkan 1.3 and use the target env when calling spirv-val.

Just curious here, why isn't this a case where we'd add the scalar block layout option?

@kcloudy0717 kcloudy0717 force-pushed the kcloudy0717/QuadReadAcrossDiagonal branch from 86c880e to c7cded9 Compare March 31, 2026 08:19
@bob80905

bob80905 commented Apr 9, 2026

Copy link
Copy Markdown
Contributor

Can you fix the merge conflict @kcloudy0717 ?

@kcloudy0717

Copy link
Copy Markdown
Contributor Author

Can you fix the merge conflict @kcloudy0717 ?

Sure I can fix the merge conflicts.

@kcloudy0717 kcloudy0717 force-pushed the kcloudy0717/QuadReadAcrossDiagonal branch from c7cded9 to 6da8914 Compare April 10, 2026 05:59
@kcloudy0717

Copy link
Copy Markdown
Contributor Author

@bob80905 Conflicts resolved, rebased to latest commit.

@bob80905 bob80905 closed this Apr 13, 2026
@bob80905 bob80905 reopened this Apr 13, 2026
@kcloudy0717 kcloudy0717 force-pushed the kcloudy0717/QuadReadAcrossDiagonal branch from 6da8914 to 4f1106a Compare April 15, 2026 06:20
@kcloudy0717 kcloudy0717 force-pushed the kcloudy0717/QuadReadAcrossDiagonal branch from 4f1106a to b4dc809 Compare April 26, 2026 15:46
@kcloudy0717 kcloudy0717 force-pushed the kcloudy0717/QuadReadAcrossDiagonal branch from b4dc809 to a79b7a6 Compare May 3, 2026 20:14
@kcloudy0717 kcloudy0717 force-pushed the kcloudy0717/QuadReadAcrossDiagonal branch from a79b7a6 to bfb12b1 Compare June 4, 2026 13:03

@bogner bogner left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been sitting for a while - do you need somebody to merge it for you?

I think you've made enough changes that folks were assuming you have commit access at this point - you can feel free to request it following the guidelines here: https://llvm.org/docs/DeveloperPolicy.html#obtaining-commit-access. Feel free to CC me to give an approval.

@kcloudy0717

Copy link
Copy Markdown
Contributor Author

This has been sitting for a while - do you need somebody to merge it for you?

I think you've made enough changes that folks were assuming you have commit access at this point - you can feel free to request it following the guidelines here: https://llvm.org/docs/DeveloperPolicy.html#obtaining-commit-access. Feel free to CC me to give an approval.

Yea, could you merge it for me? I still don't have access to the repo, and I wasn't sure what requirements are needed to gain access. I will now apply for the access, thank you :)

@bogner bogner merged commit 8a3cc84 into llvm:main Jun 16, 2026
12 of 13 checks passed
@bogner

bogner commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

I've merged it and put up the XFAIL update here: llvm/offload-test-suite#1316

bogner added a commit to llvm/offload-test-suite that referenced this pull request Jun 16, 2026
nasherm pushed a commit to nasherm/llvm-project that referenced this pull request Jun 18, 2026
…8567)

This PR adds QuadReadAcrossDiagonal intrinsic support in HLSL with
codegen for both DirectX and SPIRV backends. Resolves
llvm#99177.

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

---------

Co-authored-by: Justin Bogner <mail@justinbogner.com>
joaosaffran pushed a commit to joaosaffran/offload-test-suite that referenced this pull request Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:DirectX backend:SPIR-V backend:X86 clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:headers Headers provided by Clang, e.g. for intrinsics HLSL HLSL Language Support llvm:ir

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement the QuadReadAcrossDiagonal HLSL Function

5 participants