[clang] [HLSL][LongVec] Add more intrinsic support (PR #222043)
Farzon Lotfi via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 15 13:07:50 PDT 2026
https://github.com/farzonl updated https://github.com/llvm/llvm-project/pull/222043
>From 4ee922688f5a015961d6b928648be6195bc80fc1 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Thu, 3 Sep 2026 16:59:07 -0400
Subject: [PATCH 1/5] [HLSL][LongVec] Add more intrinsic support
resolves #220699
resolves #220655
resolves #220639
resolves #220638
resolves #220614
---
clang/include/clang/Basic/HLSLIntrinsics.td | 5 +++++
clang/test/CodeGenHLSL/builtins/asdouble.hlsl | 12 ++++++++++++
clang/test/CodeGenHLSL/builtins/ddx.hlsl | 7 +++++++
clang/test/CodeGenHLSL/builtins/ddy.hlsl | 7 +++++++
clang/test/CodeGenHLSL/builtins/ldexp.hlsl | 6 ++++++
clang/test/CodeGenHLSL/builtins/mad.hlsl | 7 +++++++
6 files changed, 44 insertions(+)
diff --git a/clang/include/clang/Basic/HLSLIntrinsics.td b/clang/include/clang/Basic/HLSLIntrinsics.td
index ecf7c3df31fe8..21c0960b6fa23 100644
--- a/clang/include/clang/Basic/HLSLIntrinsics.td
+++ b/clang/include/clang/Basic/HLSLIntrinsics.td
@@ -427,6 +427,7 @@ def hlsl_asdouble : HLSLTwoArgBuiltin<"asdouble", "__builtin_hlsl_asdouble"> {
}];
let ReturnType = VaryingShape<DoubleTy>;
let VaryingTypes = [UIntTy];
+ let VaryingLongVector = 1;
let VaryingMatDims = [];
}
@@ -600,6 +601,7 @@ the screen-space x-coordinate.
}];
let ParamNames = ["input"];
let VaryingTypes = [HalfTy, FloatTy];
+ let VaryingLongVector = 1;
let VaryingMatDims = [];
}
@@ -649,6 +651,7 @@ the screen-space y-coordinate.
}];
let ParamNames = ["input"];
let VaryingTypes = [HalfTy, FloatTy];
+ let VaryingLongVector = 1;
let VaryingMatDims = [];
}
@@ -1141,6 +1144,7 @@ This function uses the following formula: X * 2^Exp
let VaryingTypes = [HalfTy, FloatTy];
let VaryingScalar = 1;
let VaryingVecSizes = [2, 3, 4];
+ let VaryingLongVector = 1;
let VaryingMatDims = [];
}
@@ -1264,6 +1268,7 @@ def hlsl_mad : HLSLThreeArgBuiltin<"mad", "__builtin_hlsl_mad"> {
}];
let VaryingTypes = AllNumericTypes;
let VaryingMatDims = [];
+ let VaryingLongVector = 1;
}
// Returns the greater of X and Y.
diff --git a/clang/test/CodeGenHLSL/builtins/asdouble.hlsl b/clang/test/CodeGenHLSL/builtins/asdouble.hlsl
index e73f9ad35ebe2..2753b416d7440 100644
--- a/clang/test/CodeGenHLSL/builtins/asdouble.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/asdouble.hlsl
@@ -35,3 +35,15 @@ double3 test_vuint(uint3 low, uint3 high) {
}
// CHECK-DXIL: declare <3 x double> @llvm.dx.asdouble.v3i32
+
+// CHECK-LABEL: test_vuint5
+vector<double, 5> test_vuint5(vector<uint, 5> low, vector<uint, 5> high) {
+ // CHECK-SPV: %[[SHUFFLE2:.*]] = shufflevector
+ // CHECK-SPV-SAME: {{.*}} <i32 0, i32 5, i32 1, i32 6, i32 2, i32 7, i32 3, i32 8, i32 4, i32 9>
+ // CHECK-SPV: bitcast <10 x i32> %[[SHUFFLE2]] to <5 x double>
+
+ // CHECK-DXIL: call reassoc nnan ninf nsz arcp afn <5 x double> @llvm.dx.asdouble.v5i32
+ return asdouble(low, high);
+}
+
+// CHECK-DXIL: declare <5 x double> @llvm.dx.asdouble.v5i32
diff --git a/clang/test/CodeGenHLSL/builtins/ddx.hlsl b/clang/test/CodeGenHLSL/builtins/ddx.hlsl
index e673e1985dd60..7ec896ee27851 100644
--- a/clang/test/CodeGenHLSL/builtins/ddx.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ddx.hlsl
@@ -60,3 +60,10 @@ float3 test_f32_ddx3(float3 val) {
float4 test_f32_ddx4(float4 val) {
return ddx(val);
}
+
+// CHECK-LABEL: define {{.*}} <5 x float> @_ZN4hlsl8__detail8ddx_impl
+// CHECK: %[[VAR]] = call {{.*}} <5 x float> @llvm.[[CALL]].v5f32(<5 x float> %{{.*}})
+// CHECK: ret <5 x float> %[[VAR]]
+vector<float, 5> test_f32_ddx5(vector<float, 5> val) {
+ return ddx(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy.hlsl b/clang/test/CodeGenHLSL/builtins/ddy.hlsl
index 80d75ca7b22c3..d330d589e918b 100644
--- a/clang/test/CodeGenHLSL/builtins/ddy.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ddy.hlsl
@@ -60,3 +60,10 @@ float3 test_f32_ddy3(float3 val) {
float4 test_f32_ddy4(float4 val) {
return ddy(val);
}
+
+// CHECK-LABEL: define {{.*}} <5 x float> @_ZN4hlsl8__detail8ddy_impl
+// CHECK: %[[VAR]] = call {{.*}} <5 x float> @llvm.[[CALL]].v5f32(<5 x float> %{{.*}})
+// CHECK: ret <5 x float> %[[VAR]]
+vector<float, 5> test_f32_ddy5(vector<float, 5> val) {
+ return ddy(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ldexp.hlsl b/clang/test/CodeGenHLSL/builtins/ldexp.hlsl
index 2c0458d079027..170c635e99b61 100644
--- a/clang/test/CodeGenHLSL/builtins/ldexp.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ldexp.hlsl
@@ -47,3 +47,9 @@ float3 test_ldexp_float3(float3 X, float3 Exp) { return ldexp(X, Exp); }
// CHECK: [[MUL:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> [[EXP2]], %{{.*}}
// CHECK: ret <4 x float> [[MUL]]
float4 test_ldexp_float4(float4 X, float4 Exp) { return ldexp(X, Exp); }
+
+// CHECK-LABEL: define linkonce_odr hidden noundef nofpclass(nan inf) <5 x float> @_ZN4hlsl5ldexp
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <5 x float> @llvm.exp2.v5f32(<5 x float> %{{.*}})
+// CHECK: [[MUL:%.*]] = fmul reassoc nnan ninf nsz arcp afn <5 x float> [[EXP2]], %{{.*}}
+// CHECK: ret <5 x float> [[MUL]]
+vector<float, 5> test_ldexp_float5(vector<float, 5> X, vector<float, 5> Exp) { return ldexp(X, Exp); }
diff --git a/clang/test/CodeGenHLSL/builtins/mad.hlsl b/clang/test/CodeGenHLSL/builtins/mad.hlsl
index d982ecba848e2..8ee6d3aac2185 100644
--- a/clang/test/CodeGenHLSL/builtins/mad.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/mad.hlsl
@@ -140,6 +140,13 @@ float3 test_mad_float3(float3 p0, float3 p1, float3 p2) { return mad(p0, p1, p2)
// CHECK: ret <4 x float> %hlsl.fmad
float4 test_mad_float4(float4 p0, float4 p1, float4 p2) { return mad(p0, p1, p2); }
+// CHECK: %[[p0:.*]] = load <5 x float>, ptr %p0.addr
+// CHECK: %[[p1:.*]] = load <5 x float>, ptr %p1.addr
+// CHECK: %[[p2:.*]] = load <5 x float>, ptr %p2.addr
+// CHECK: %hlsl.fmad = call reassoc nnan ninf nsz arcp afn <5 x float> @llvm.fmuladd.v5f32(<5 x float> %[[p0]], <5 x float> %[[p1]], <5 x float> %[[p2]])
+// CHECK: ret <5 x float> %hlsl.fmad
+vector<float, 5> test_mad_float5(vector<float, 5> p0, vector<float, 5> p1, vector<float, 5> p2) { return mad(p0, p1, p2); }
+
// CHECK: %[[p0:.*]] = load double, ptr %p0.addr
// CHECK: %[[p1:.*]] = load double, ptr %p1.addr
// CHECK: %[[p2:.*]] = load double, ptr %p2.addr
>From dede60edddffcf6f22bd53c1f90e70eedbc70951 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Tue, 8 Sep 2026 14:56:08 -0400
Subject: [PATCH 2/5] add missing test change
---
clang/test/SemaHLSL/BuiltIns/ldexp-errors.hlsl | 8 --------
1 file changed, 8 deletions(-)
diff --git a/clang/test/SemaHLSL/BuiltIns/ldexp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ldexp-errors.hlsl
index ce15550d7884b..e269918d85938 100644
--- a/clang/test/SemaHLSL/BuiltIns/ldexp-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/ldexp-errors.hlsl
@@ -16,11 +16,3 @@ float1 test_vec1_inputs(float1 p0, float1 p1) {
return ldexp(p0, p1);
// expected-warning at -1 2 {{implicit conversion turns vector to scalar: 'float1' (aka 'vector<float, 1>') to 'float'}}
}
-
-typedef float float5 __attribute__((ext_vector_type(5)));
-
-float5 test_vec5_inputs(float5 p0, float5 p1) {
- return ldexp(p0, p1);
- // expected-error at -1 {{call to 'ldexp' is ambiguous}}
- // expected-note at hlsl/hlsl_inline_intrinsics_gen.inc:* 4 {{candidate function}}
-}
>From 44ff277aa60f3571460f9f0a60abb97ef5232af0 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Tue, 15 Sep 2026 11:48:10 -0400
Subject: [PATCH 3/5] update mad to have check labels
---
clang/test/CodeGenHLSL/builtins/mad.hlsl | 40 +++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/clang/test/CodeGenHLSL/builtins/mad.hlsl b/clang/test/CodeGenHLSL/builtins/mad.hlsl
index 8ee6d3aac2185..f7ea6232856e6 100644
--- a/clang/test/CodeGenHLSL/builtins/mad.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/mad.hlsl
@@ -15,48 +15,57 @@
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF,SPIR_CHECK
#ifdef __HLSL_ENABLE_16_BIT
+
+// CHECK-LABEL: test_mad_uint16_t
// DXIL_NATIVE_HALF: %dx.umad = call i16 @llvm.dx.umad.i16(i16 %[[#]], i16 %[[#]], i16 %[[#]])
// DXIL_NATIVE_HALF: ret i16 %dx.umad
// SPIR_NATIVE_HALF: mul nuw i16 %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nuw i16 %{{.*}}, %{{.*}}
uint16_t test_mad_uint16_t(uint16_t p0, uint16_t p1, uint16_t p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_uint16_t2
// DXIL_NATIVE_HALF: %dx.umad = call <2 x i16> @llvm.dx.umad.v2i16(<2 x i16> %[[#]], <2 x i16> %[[#]], <2 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <2 x i16> %dx.umad
// SPIR_NATIVE_HALF: mul nuw <2 x i16> %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nuw <2 x i16> %{{.*}}, %{{.*}}
uint16_t2 test_mad_uint16_t2(uint16_t2 p0, uint16_t2 p1, uint16_t2 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_uint16_t3
// DXIL_NATIVE_HALF: %dx.umad = call <3 x i16> @llvm.dx.umad.v3i16(<3 x i16> %[[#]], <3 x i16> %[[#]], <3 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <3 x i16> %dx.umad
// SPIR_NATIVE_HALF: mul nuw <3 x i16> %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nuw <3 x i16> %{{.*}}, %{{.*}}
uint16_t3 test_mad_uint16_t3(uint16_t3 p0, uint16_t3 p1, uint16_t3 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_uint16_t4
// DXIL_NATIVE_HALF: %dx.umad = call <4 x i16> @llvm.dx.umad.v4i16(<4 x i16> %[[#]], <4 x i16> %[[#]], <4 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <4 x i16> %dx.umad
// SPIR_NATIVE_HALF: mul nuw <4 x i16> %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nuw <4 x i16> %{{.*}}, %{{.*}}
uint16_t4 test_mad_uint16_t4(uint16_t4 p0, uint16_t4 p1, uint16_t4 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_int16_t
// DXIL_NATIVE_HALF: %dx.imad = call i16 @llvm.dx.imad.i16(i16 %[[#]], i16 %[[#]], i16 %[[#]])
// DXIL_NATIVE_HALF: ret i16 %dx.imad
// SPIR_NATIVE_HALF: mul nsw i16 %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nsw i16 %{{.*}}, %{{.*}}
int16_t test_mad_int16_t(int16_t p0, int16_t p1, int16_t p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_int16_t2
// DXIL_NATIVE_HALF: %dx.imad = call <2 x i16> @llvm.dx.imad.v2i16(<2 x i16> %[[#]], <2 x i16> %[[#]], <2 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <2 x i16> %dx.imad
// SPIR_NATIVE_HALF: mul nsw <2 x i16> %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nsw <2 x i16> %{{.*}}, %{{.*}}
int16_t2 test_mad_int16_t2(int16_t2 p0, int16_t2 p1, int16_t2 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_int16_t3
// DXIL_NATIVE_HALF: %dx.imad = call <3 x i16> @llvm.dx.imad.v3i16(<3 x i16> %[[#]], <3 x i16> %[[#]], <3 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <3 x i16> %dx.imad
// SPIR_NATIVE_HALF: mul nsw <3 x i16> %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nsw <3 x i16> %{{.*}}, %{{.*}}
int16_t3 test_mad_int16_t3(int16_t3 p0, int16_t3 p1, int16_t3 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_int16_t4
// DXIL_NATIVE_HALF: %dx.imad = call <4 x i16> @llvm.dx.imad.v4i16(<4 x i16> %[[#]], <4 x i16> %[[#]], <4 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <4 x i16> %dx.imad
// SPIR_NATIVE_HALF: mul nsw <4 x i16> %{{.*}}, %{{.*}}
@@ -64,6 +73,7 @@ int16_t3 test_mad_int16_t3(int16_t3 p0, int16_t3 p1, int16_t3 p2) { return mad(p
int16_t4 test_mad_int16_t4(int16_t4 p0, int16_t4 p1, int16_t4 p2) { return mad(p0, p1, p2); }
#endif // __HLSL_ENABLE_16_BIT
+// CHECK-LABEL: test_mad_half
// NATIVE_HALF: %[[p0:.*]] = load half, ptr %p0.addr
// NATIVE_HALF: %[[p1:.*]] = load half, ptr %p1.addr
// NATIVE_HALF: %[[p2:.*]] = load half, ptr %p2.addr
@@ -76,6 +86,7 @@ int16_t4 test_mad_int16_t4(int16_t4 p0, int16_t4 p1, int16_t4 p2) { return mad(p
// NO_HALF: ret float %hlsl.fmad
half test_mad_half(half p0, half p1, half p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_half2
// NATIVE_HALF: %[[p0:.*]] = load <2 x half>, ptr %p0.addr
// NATIVE_HALF: %[[p1:.*]] = load <2 x half>, ptr %p1.addr
// NATIVE_HALF: %[[p2:.*]] = load <2 x half>, ptr %p2.addr
@@ -88,6 +99,7 @@ half test_mad_half(half p0, half p1, half p2) { return mad(p0, p1, p2); }
// NO_HALF: ret <2 x float> %hlsl.fmad
half2 test_mad_half2(half2 p0, half2 p1, half2 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_half3
// NATIVE_HALF: %[[p0:.*]] = load <3 x half>, ptr %p0.addr
// NATIVE_HALF: %[[p1:.*]] = load <3 x half>, ptr %p1.addr
// NATIVE_HALF: %[[p2:.*]] = load <3 x half>, ptr %p2.addr
@@ -100,6 +112,7 @@ half2 test_mad_half2(half2 p0, half2 p1, half2 p2) { return mad(p0, p1, p2); }
// NO_HALF: ret <3 x float> %hlsl.fmad
half3 test_mad_half3(half3 p0, half3 p1, half3 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_half4
// NATIVE_HALF: %[[p0:.*]] = load <4 x half>, ptr %p0.addr
// NATIVE_HALF: %[[p1:.*]] = load <4 x half>, ptr %p1.addr
// NATIVE_HALF: %[[p2:.*]] = load <4 x half>, ptr %p2.addr
@@ -112,6 +125,7 @@ half3 test_mad_half3(half3 p0, half3 p1, half3 p2) { return mad(p0, p1, p2); }
// NO_HALF: ret <4 x float> %hlsl.fmad
half4 test_mad_half4(half4 p0, half4 p1, half4 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_float
// CHECK: %[[p0:.*]] = load float, ptr %p0.addr
// CHECK: %[[p1:.*]] = load float, ptr %p1.addr
// CHECK: %[[p2:.*]] = load float, ptr %p2.addr
@@ -119,6 +133,7 @@ half4 test_mad_half4(half4 p0, half4 p1, half4 p2) { return mad(p0, p1, p2); }
// CHECK: ret float %hlsl.fmad
float test_mad_float(float p0, float p1, float p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_float2
// CHECK: %[[p0:.*]] = load <2 x float>, ptr %p0.addr
// CHECK: %[[p1:.*]] = load <2 x float>, ptr %p1.addr
// CHECK: %[[p2:.*]] = load <2 x float>, ptr %p2.addr
@@ -126,6 +141,7 @@ float test_mad_float(float p0, float p1, float p2) { return mad(p0, p1, p2); }
// CHECK: ret <2 x float> %hlsl.fmad
float2 test_mad_float2(float2 p0, float2 p1, float2 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_float3
// CHECK: %[[p0:.*]] = load <3 x float>, ptr %p0.addr
// CHECK: %[[p1:.*]] = load <3 x float>, ptr %p1.addr
// CHECK: %[[p2:.*]] = load <3 x float>, ptr %p2.addr
@@ -133,6 +149,7 @@ float2 test_mad_float2(float2 p0, float2 p1, float2 p2) { return mad(p0, p1, p2)
// CHECK: ret <3 x float> %hlsl.fmad
float3 test_mad_float3(float3 p0, float3 p1, float3 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_float4
// CHECK: %[[p0:.*]] = load <4 x float>, ptr %p0.addr
// CHECK: %[[p1:.*]] = load <4 x float>, ptr %p1.addr
// CHECK: %[[p2:.*]] = load <4 x float>, ptr %p2.addr
@@ -140,6 +157,7 @@ float3 test_mad_float3(float3 p0, float3 p1, float3 p2) { return mad(p0, p1, p2)
// CHECK: ret <4 x float> %hlsl.fmad
float4 test_mad_float4(float4 p0, float4 p1, float4 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_float5
// CHECK: %[[p0:.*]] = load <5 x float>, ptr %p0.addr
// CHECK: %[[p1:.*]] = load <5 x float>, ptr %p1.addr
// CHECK: %[[p2:.*]] = load <5 x float>, ptr %p2.addr
@@ -147,6 +165,7 @@ float4 test_mad_float4(float4 p0, float4 p1, float4 p2) { return mad(p0, p1, p2)
// CHECK: ret <5 x float> %hlsl.fmad
vector<float, 5> test_mad_float5(vector<float, 5> p0, vector<float, 5> p1, vector<float, 5> p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_double
// CHECK: %[[p0:.*]] = load double, ptr %p0.addr
// CHECK: %[[p1:.*]] = load double, ptr %p1.addr
// CHECK: %[[p2:.*]] = load double, ptr %p2.addr
@@ -154,6 +173,7 @@ vector<float, 5> test_mad_float5(vector<float, 5> p0, vector<float, 5> p1, vecto
// CHECK: ret double %hlsl.fmad
double test_mad_double(double p0, double p1, double p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_double2
// CHECK: %[[p0:.*]] = load <2 x double>, ptr %p0.addr
// CHECK: %[[p1:.*]] = load <2 x double>, ptr %p1.addr
// CHECK: %[[p2:.*]] = load <2 x double>, ptr %p2.addr
@@ -161,6 +181,7 @@ double test_mad_double(double p0, double p1, double p2) { return mad(p0, p1, p2)
// CHECK: ret <2 x double> %hlsl.fmad
double2 test_mad_double2(double2 p0, double2 p1, double2 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_double3
// CHECK: %[[p0:.*]] = load <3 x double>, ptr %p0.addr
// CHECK: %[[p1:.*]] = load <3 x double>, ptr %p1.addr
// CHECK: %[[p2:.*]] = load <3 x double>, ptr %p2.addr
@@ -168,6 +189,7 @@ double2 test_mad_double2(double2 p0, double2 p1, double2 p2) { return mad(p0, p1
// CHECK: ret <3 x double> %hlsl.fmad
double3 test_mad_double3(double3 p0, double3 p1, double3 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_double4
// CHECK: %[[p0:.*]] = load <4 x double>, ptr %p0.addr
// CHECK: %[[p1:.*]] = load <4 x double>, ptr %p1.addr
// CHECK: %[[p2:.*]] = load <4 x double>, ptr %p2.addr
@@ -175,96 +197,112 @@ double3 test_mad_double3(double3 p0, double3 p1, double3 p2) { return mad(p0, p1
// CHECK: ret <4 x double> %hlsl.fmad
double4 test_mad_double4(double4 p0, double4 p1, double4 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_int
// DXIL_CHECK: %dx.imad = call i32 @llvm.dx.imad.i32(i32 %[[#]], i32 %[[#]], i32 %[[#]])
// DXIL_CHECK: ret i32 %dx.imad
// SPIR_CHECK: mul nsw i32 %{{.*}}, %{{.*}}
// SPIR_CHECK: add nsw i32 %{{.*}}, %{{.*}}
int test_mad_int(int p0, int p1, int p2) { return mad(p0, p1, p2); }
-
+
+// CHECK-LABEL: test_mad_int2
// DXIL_CHECK: %dx.imad = call <2 x i32> @llvm.dx.imad.v2i32(<2 x i32> %[[#]], <2 x i32> %[[#]], <2 x i32> %[[#]])
// DXIL_CHECK: ret <2 x i32> %dx.imad
// SPIR_CHECK: mul nsw <2 x i32> %{{.*}}, %{{.*}}
// SPIR_CHECK: add nsw <2 x i32> %{{.*}}, %{{.*}}
int2 test_mad_int2(int2 p0, int2 p1, int2 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_int3
// DXIL_CHECK: %dx.imad = call <3 x i32> @llvm.dx.imad.v3i32(<3 x i32> %[[#]], <3 x i32> %[[#]], <3 x i32> %[[#]])
// DXIL_CHECK: ret <3 x i32> %dx.imad
// SPIR_CHECK: mul nsw <3 x i32> %{{.*}}, %{{.*}}
// SPIR_CHECK: add nsw <3 x i32> %{{.*}}, %{{.*}}
int3 test_mad_int3(int3 p0, int3 p1, int3 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_int4
// DXIL_CHECK: %dx.imad = call <4 x i32> @llvm.dx.imad.v4i32(<4 x i32> %[[#]], <4 x i32> %[[#]], <4 x i32> %[[#]])
// DXIL_CHECK: ret <4 x i32> %dx.imad
// SPIR_CHECK: mul nsw <4 x i32> %{{.*}}, %{{.*}}
// SPIR_CHECK: add nsw <4 x i32> %{{.*}}, %{{.*}}
int4 test_mad_int4(int4 p0, int4 p1, int4 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_int64_t
// DXIL_CHECK: %dx.imad = call i64 @llvm.dx.imad.i64(i64 %[[#]], i64 %[[#]], i64 %[[#]])
// DXIL_CHECK: ret i64 %dx.imad
// SPIR_CHECK: mul nsw i64 %{{.*}}, %{{.*}}
// SPIR_CHECK: add nsw i64 %{{.*}}, %{{.*}}
int64_t test_mad_int64_t(int64_t p0, int64_t p1, int64_t p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_int64_t2
// DXIL_CHECK: %dx.imad = call <2 x i64> @llvm.dx.imad.v2i64(<2 x i64> %[[#]], <2 x i64> %[[#]], <2 x i64> %[[#]])
// DXIL_CHECK: ret <2 x i64> %dx.imad
// SPIR_CHECK: mul nsw <2 x i64> %{{.*}}, %{{.*}}
// SPIR_CHECK: add nsw <2 x i64> %{{.*}}, %{{.*}}
int64_t2 test_mad_int64_t2(int64_t2 p0, int64_t2 p1, int64_t2 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_int64_t3
// DXIL_CHECK: %dx.imad = call <3 x i64> @llvm.dx.imad.v3i64(<3 x i64> %[[#]], <3 x i64> %[[#]], <3 x i64> %[[#]])
// DXIL_CHECK: ret <3 x i64> %dx.imad
// SPIR_CHECK: mul nsw <3 x i64> %{{.*}}, %{{.*}}
// SPIR_CHECK: add nsw <3 x i64> %{{.*}}, %{{.*}}
int64_t3 test_mad_int64_t3(int64_t3 p0, int64_t3 p1, int64_t3 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_int64_t4
// DXIL_CHECK: %dx.imad = call <4 x i64> @llvm.dx.imad.v4i64(<4 x i64> %[[#]], <4 x i64> %[[#]], <4 x i64> %[[#]])
// DXIL_CHECK: ret <4 x i64> %dx.imad
// SPIR_CHECK: mul nsw <4 x i64> %{{.*}}, %{{.*}}
// SPIR_CHECK: add nsw <4 x i64> %{{.*}}, %{{.*}}
int64_t4 test_mad_int64_t4(int64_t4 p0, int64_t4 p1, int64_t4 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_uint
// DXIL_CHECK: %dx.umad = call i32 @llvm.dx.umad.i32(i32 %[[#]], i32 %[[#]], i32 %[[#]])
// DXIL_CHECK: ret i32 %dx.umad
// SPIR_CHECK: mul nuw i32 %{{.*}}, %{{.*}}
// SPIR_CHECK: add nuw i32 %{{.*}}, %{{.*}}
uint test_mad_uint(uint p0, uint p1, uint p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_uint2
// DXIL_CHECK: %dx.umad = call <2 x i32> @llvm.dx.umad.v2i32(<2 x i32> %[[#]], <2 x i32> %[[#]], <2 x i32> %[[#]])
// DXIL_CHECK: ret <2 x i32> %dx.umad
// SPIR_CHECK: mul nuw <2 x i32> %{{.*}}, %{{.*}}
// SPIR_CHECK: add nuw <2 x i32> %{{.*}}, %{{.*}}
uint2 test_mad_uint2(uint2 p0, uint2 p1, uint2 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_uint3
// DXIL_CHECK: %dx.umad = call <3 x i32> @llvm.dx.umad.v3i32(<3 x i32> %[[#]], <3 x i32> %[[#]], <3 x i32> %[[#]])
// DXIL_CHECK: ret <3 x i32> %dx.umad
// SPIR_CHECK: mul nuw <3 x i32> %{{.*}}, %{{.*}}
// SPIR_CHECK: add nuw <3 x i32> %{{.*}}, %{{.*}}
uint3 test_mad_uint3(uint3 p0, uint3 p1, uint3 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_uint4
// DXIL_CHECK: %dx.umad = call <4 x i32> @llvm.dx.umad.v4i32(<4 x i32> %[[#]], <4 x i32> %[[#]], <4 x i32> %[[#]])
// DXIL_CHECK: ret <4 x i32> %dx.umad
// SPIR_CHECK: mul nuw <4 x i32> %{{.*}}, %{{.*}}
// SPIR_CHECK: add nuw <4 x i32> %{{.*}}, %{{.*}}
uint4 test_mad_uint4(uint4 p0, uint4 p1, uint4 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_uint64_t
// DXIL_CHECK: %dx.umad = call i64 @llvm.dx.umad.i64(i64 %[[#]], i64 %[[#]], i64 %[[#]])
// DXIL_CHECK: ret i64 %dx.umad
// SPIR_CHECK: mul nuw i64 %{{.*}}, %{{.*}}
// SPIR_CHECK: add nuw i64 %{{.*}}, %{{.*}}
uint64_t test_mad_uint64_t(uint64_t p0, uint64_t p1, uint64_t p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_uint64_t2
// DXIL_CHECK: %dx.umad = call <2 x i64> @llvm.dx.umad.v2i64(<2 x i64> %[[#]], <2 x i64> %[[#]], <2 x i64> %[[#]])
// DXIL_CHECK: ret <2 x i64> %dx.umad
// SPIR_CHECK: mul nuw <2 x i64> %{{.*}}, %{{.*}}
// SPIR_CHECK: add nuw <2 x i64> %{{.*}}, %{{.*}}
uint64_t2 test_mad_uint64_t2(uint64_t2 p0, uint64_t2 p1, uint64_t2 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_uint64_t3
// DXIL_CHECK: %dx.umad = call <3 x i64> @llvm.dx.umad.v3i64(<3 x i64> %[[#]], <3 x i64> %[[#]], <3 x i64> %[[#]])
// DXIL_CHECK: ret <3 x i64> %dx.umad
// SPIR_CHECK: mul nuw <3 x i64> %{{.*}}, %{{.*}}
// SPIR_CHECK: add nuw <3 x i64> %{{.*}}, %{{.*}}
uint64_t3 test_mad_uint64_t3(uint64_t3 p0, uint64_t3 p1, uint64_t3 p2) { return mad(p0, p1, p2); }
+// CHECK-LABEL: test_mad_uint64_t4
// DXIL_CHECK: %dx.umad = call <4 x i64> @llvm.dx.umad.v4i64(<4 x i64> %[[#]], <4 x i64> %[[#]], <4 x i64> %[[#]])
// DXIL_CHECK: ret <4 x i64> %dx.umad
// SPIR_CHECK: mul nuw <4 x i64> %{{.*}}, %{{.*}}
>From 7c58bc082a09024cd59ac1b3857d41e94e03cbd6 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Tue, 15 Sep 2026 15:57:26 -0400
Subject: [PATCH 4/5] add labels as per pr request
---
clang/test/CodeGenHLSL/builtins/mad.hlsl | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/clang/test/CodeGenHLSL/builtins/mad.hlsl b/clang/test/CodeGenHLSL/builtins/mad.hlsl
index f7ea6232856e6..e45fb0bc20383 100644
--- a/clang/test/CodeGenHLSL/builtins/mad.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/mad.hlsl
@@ -16,56 +16,56 @@
#ifdef __HLSL_ENABLE_16_BIT
-// CHECK-LABEL: test_mad_uint16_t
+// NATIVE_HALF-LABEL: test_mad_uint16_t
// DXIL_NATIVE_HALF: %dx.umad = call i16 @llvm.dx.umad.i16(i16 %[[#]], i16 %[[#]], i16 %[[#]])
// DXIL_NATIVE_HALF: ret i16 %dx.umad
// SPIR_NATIVE_HALF: mul nuw i16 %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nuw i16 %{{.*}}, %{{.*}}
uint16_t test_mad_uint16_t(uint16_t p0, uint16_t p1, uint16_t p2) { return mad(p0, p1, p2); }
-// CHECK-LABEL: test_mad_uint16_t2
+// NATIVE_HALF-LABEL: test_mad_uint16_t2
// DXIL_NATIVE_HALF: %dx.umad = call <2 x i16> @llvm.dx.umad.v2i16(<2 x i16> %[[#]], <2 x i16> %[[#]], <2 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <2 x i16> %dx.umad
// SPIR_NATIVE_HALF: mul nuw <2 x i16> %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nuw <2 x i16> %{{.*}}, %{{.*}}
uint16_t2 test_mad_uint16_t2(uint16_t2 p0, uint16_t2 p1, uint16_t2 p2) { return mad(p0, p1, p2); }
-// CHECK-LABEL: test_mad_uint16_t3
+// NATIVE_HALF-LABEL: test_mad_uint16_t3
// DXIL_NATIVE_HALF: %dx.umad = call <3 x i16> @llvm.dx.umad.v3i16(<3 x i16> %[[#]], <3 x i16> %[[#]], <3 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <3 x i16> %dx.umad
// SPIR_NATIVE_HALF: mul nuw <3 x i16> %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nuw <3 x i16> %{{.*}}, %{{.*}}
uint16_t3 test_mad_uint16_t3(uint16_t3 p0, uint16_t3 p1, uint16_t3 p2) { return mad(p0, p1, p2); }
-// CHECK-LABEL: test_mad_uint16_t4
+// NATIVE_HALF-LABEL: test_mad_uint16_t4
// DXIL_NATIVE_HALF: %dx.umad = call <4 x i16> @llvm.dx.umad.v4i16(<4 x i16> %[[#]], <4 x i16> %[[#]], <4 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <4 x i16> %dx.umad
// SPIR_NATIVE_HALF: mul nuw <4 x i16> %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nuw <4 x i16> %{{.*}}, %{{.*}}
uint16_t4 test_mad_uint16_t4(uint16_t4 p0, uint16_t4 p1, uint16_t4 p2) { return mad(p0, p1, p2); }
-// CHECK-LABEL: test_mad_int16_t
+// NATIVE_HALF-LABEL: test_mad_int16_t
// DXIL_NATIVE_HALF: %dx.imad = call i16 @llvm.dx.imad.i16(i16 %[[#]], i16 %[[#]], i16 %[[#]])
// DXIL_NATIVE_HALF: ret i16 %dx.imad
// SPIR_NATIVE_HALF: mul nsw i16 %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nsw i16 %{{.*}}, %{{.*}}
int16_t test_mad_int16_t(int16_t p0, int16_t p1, int16_t p2) { return mad(p0, p1, p2); }
-// CHECK-LABEL: test_mad_int16_t2
+// NATIVE_HALF-LABEL: test_mad_int16_t2
// DXIL_NATIVE_HALF: %dx.imad = call <2 x i16> @llvm.dx.imad.v2i16(<2 x i16> %[[#]], <2 x i16> %[[#]], <2 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <2 x i16> %dx.imad
// SPIR_NATIVE_HALF: mul nsw <2 x i16> %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nsw <2 x i16> %{{.*}}, %{{.*}}
int16_t2 test_mad_int16_t2(int16_t2 p0, int16_t2 p1, int16_t2 p2) { return mad(p0, p1, p2); }
-// CHECK-LABEL: test_mad_int16_t3
+// NATIVE_HALF-LABEL: test_mad_int16_t3
// DXIL_NATIVE_HALF: %dx.imad = call <3 x i16> @llvm.dx.imad.v3i16(<3 x i16> %[[#]], <3 x i16> %[[#]], <3 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <3 x i16> %dx.imad
// SPIR_NATIVE_HALF: mul nsw <3 x i16> %{{.*}}, %{{.*}}
// SPIR_NATIVE_HALF: add nsw <3 x i16> %{{.*}}, %{{.*}}
int16_t3 test_mad_int16_t3(int16_t3 p0, int16_t3 p1, int16_t3 p2) { return mad(p0, p1, p2); }
-// CHECK-LABEL: test_mad_int16_t4
+// NATIVE_HALF-LABEL: test_mad_int16_t4
// DXIL_NATIVE_HALF: %dx.imad = call <4 x i16> @llvm.dx.imad.v4i16(<4 x i16> %[[#]], <4 x i16> %[[#]], <4 x i16> %[[#]])
// DXIL_NATIVE_HALF: ret <4 x i16> %dx.imad
// SPIR_NATIVE_HALF: mul nsw <4 x i16> %{{.*}}, %{{.*}}
>From 544b3bcc69ba08bde938126d669748299eb2efdc Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Tue, 15 Sep 2026 16:07:29 -0400
Subject: [PATCH 5/5] make asdouble tests varify inputs
---
clang/test/CodeGenHLSL/builtins/asdouble.hlsl | 35 +++++++++++++------
1 file changed, 25 insertions(+), 10 deletions(-)
diff --git a/clang/test/CodeGenHLSL/builtins/asdouble.hlsl b/clang/test/CodeGenHLSL/builtins/asdouble.hlsl
index 2753b416d7440..a509571cd8f54 100644
--- a/clang/test/CodeGenHLSL/builtins/asdouble.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/asdouble.hlsl
@@ -7,42 +7,57 @@
// Test lowering of asdouble expansion to shuffle/bitcast and splat when required
-// CHECK-LABEL: test_uint
+// CHECK-LABEL: define {{.*}}test_uint
+// CHECK-SAME: (i32 noundef %[[LOW_ARG:[^,]+]], i32 noundef %[[HIGH_ARG:[^)]+]])
double test_uint(uint low, uint high) {
- // CHECK-SPV: %[[LOW_INSERT:.*]] = insertelement <1 x i32>
+ // CHECK: store i32 %[[LOW_ARG]], ptr %[[LOW_ADDR:.*]], align 4
+ // CHECK: store i32 %[[HIGH_ARG]], ptr %[[HIGH_ADDR:.*]], align 4
+ // CHECK: %[[LOW:.*]] = load i32, ptr %[[LOW_ADDR]], align 4
+ // CHECK: %[[HIGH:.*]] = load i32, ptr %[[HIGH_ADDR]], align 4
+ // CHECK-SPV: %[[LOW_INSERT:.*]] = insertelement <1 x i32> poison, i32 %[[LOW]], i64 0
// CHECK-SPV: %[[LOW_SHUFFLE:.*]] = shufflevector <1 x i32> %[[LOW_INSERT]], {{.*}} zeroinitializer
- // CHECK-SPV: %[[HIGH_INSERT:.*]] = insertelement <1 x i32>
+ // CHECK-SPV: %[[HIGH_INSERT:.*]] = insertelement <1 x i32> poison, i32 %[[HIGH]], i64 0
// CHECK-SPV: %[[HIGH_SHUFFLE:.*]] = shufflevector <1 x i32> %[[HIGH_INSERT]], {{.*}} zeroinitializer
// CHECK-SPV: %[[SHUFFLE0:.*]] = shufflevector <1 x i32> %[[LOW_SHUFFLE]], <1 x i32> %[[HIGH_SHUFFLE]],
// CHECK-SPV-SAME: {{.*}} <i32 0, i32 1>
// CHECK-SPV: bitcast <2 x i32> %[[SHUFFLE0]] to double
- // CHECK-DXIL: call reassoc nnan ninf nsz arcp afn double @llvm.dx.asdouble.i32
+ // CHECK-DXIL: call reassoc nnan ninf nsz arcp afn double @llvm.dx.asdouble.i32(i32 %[[LOW]], i32 %[[HIGH]])
return asdouble(low, high);
}
// CHECK-DXIL: declare double @llvm.dx.asdouble.i32
-// CHECK-LABEL: test_vuint
+// CHECK-LABEL: define {{.*}}test_vuint
+// CHECK-SAME: (<3 x i32> noundef %[[V3_LOW_ARG:[^,]+]], <3 x i32> noundef %[[V3_HIGH_ARG:[^)]+]])
double3 test_vuint(uint3 low, uint3 high) {
- // CHECK-SPV: %[[SHUFFLE1:.*]] = shufflevector
+ // CHECK: store <3 x i32> %[[V3_LOW_ARG]], ptr %[[V3_LOW_ADDR:.*]], align 4
+ // CHECK: store <3 x i32> %[[V3_HIGH_ARG]], ptr %[[V3_HIGH_ADDR:.*]], align 4
+ // CHECK: %[[V3_LOW:.*]] = load <3 x i32>, ptr %[[V3_LOW_ADDR]], align 4
+ // CHECK: %[[V3_HIGH:.*]] = load <3 x i32>, ptr %[[V3_HIGH_ADDR]], align 4
+ // CHECK-SPV: %[[SHUFFLE1:.*]] = shufflevector <3 x i32> %[[V3_LOW]], <3 x i32> %[[V3_HIGH]],
// CHECK-SPV-SAME: {{.*}} <i32 0, i32 3, i32 1, i32 4, i32 2, i32 5>
// CHECK-SPV: bitcast <6 x i32> %[[SHUFFLE1]] to <3 x double>
- // CHECK-DXIL: call reassoc nnan ninf nsz arcp afn <3 x double> @llvm.dx.asdouble.v3i32
+ // CHECK-DXIL: call reassoc nnan ninf nsz arcp afn <3 x double> @llvm.dx.asdouble.v3i32(<3 x i32> %[[V3_LOW]], <3 x i32> %[[V3_HIGH]])
return asdouble(low, high);
}
// CHECK-DXIL: declare <3 x double> @llvm.dx.asdouble.v3i32
-// CHECK-LABEL: test_vuint5
+// CHECK-LABEL: define {{.*}}test_vuint5
+// CHECK-SAME: (<5 x i32> noundef %[[V5_LOW_ARG:[^,]+]], <5 x i32> noundef %[[V5_HIGH_ARG:[^)]+]])
vector<double, 5> test_vuint5(vector<uint, 5> low, vector<uint, 5> high) {
- // CHECK-SPV: %[[SHUFFLE2:.*]] = shufflevector
+ // CHECK: store <5 x i32> %[[V5_LOW_ARG]], ptr %[[V5_LOW_ADDR:.*]], align 4
+ // CHECK: store <5 x i32> %[[V5_HIGH_ARG]], ptr %[[V5_HIGH_ADDR:.*]], align 4
+ // CHECK: %[[V5_LOW:.*]] = load <5 x i32>, ptr %[[V5_LOW_ADDR]], align 4
+ // CHECK: %[[V5_HIGH:.*]] = load <5 x i32>, ptr %[[V5_HIGH_ADDR]], align 4
+ // CHECK-SPV: %[[SHUFFLE2:.*]] = shufflevector <5 x i32> %[[V5_LOW]], <5 x i32> %[[V5_HIGH]],
// CHECK-SPV-SAME: {{.*}} <i32 0, i32 5, i32 1, i32 6, i32 2, i32 7, i32 3, i32 8, i32 4, i32 9>
// CHECK-SPV: bitcast <10 x i32> %[[SHUFFLE2]] to <5 x double>
- // CHECK-DXIL: call reassoc nnan ninf nsz arcp afn <5 x double> @llvm.dx.asdouble.v5i32
+ // CHECK-DXIL: call reassoc nnan ninf nsz arcp afn <5 x double> @llvm.dx.asdouble.v5i32(<5 x i32> %[[V5_LOW]], <5 x i32> %[[V5_HIGH]])
return asdouble(low, high);
}
More information about the cfe-commits
mailing list