Skip to content

[HLSL] Make lerp overload tests stricter. NFC #137898

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 30, 2025

Conversation

bogner
Copy link
Contributor

@bogner bogner commented Apr 29, 2025

These tests had checks across multiple functions, because none of the hlsl header implementation functions were inlined. Switch the run lines to use -O1 instead of -disable-llvm-passes and rewrite the tests to actually look at the whole function.

Note - this would be simpler with update_cc_test_checks, but the differences between DX and SPIRV are difficult to account for with those scripts.

These tests had checks across multiple functions, because none of the hlsl
header implementation functions were inlined. Switch the run lines to use -O1
instead of -disable-llvm-passes and rewrite the tests to actually look at the
whole function.

Note - this would be simpler with update_cc_test_checks, but the differences
between DX and SPIRV are difficult to account for with those scripts.
@llvmbot llvmbot added clang Clang issues not falling into any other category HLSL HLSL Language Support labels Apr 29, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 29, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-hlsl

Author: Justin Bogner (bogner)

Changes

These tests had checks across multiple functions, because none of the hlsl header implementation functions were inlined. Switch the run lines to use -O1 instead of -disable-llvm-passes and rewrite the tests to actually look at the whole function.

Note - this would be simpler with update_cc_test_checks, but the differences between DX and SPIRV are difficult to account for with those scripts.


Full diff: https://github.com/llvm/llvm-project/pull/137898.diff

1 Files Affected:

  • (modified) clang/test/CodeGenHLSL/builtins/lerp-overloads.hlsl (+121-69)
diff --git a/clang/test/CodeGenHLSL/builtins/lerp-overloads.hlsl b/clang/test/CodeGenHLSL/builtins/lerp-overloads.hlsl
index 6e452481e2fa2..9c613ce2db27d 100644
--- a/clang/test/CodeGenHLSL/builtins/lerp-overloads.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/lerp-overloads.hlsl
@@ -1,108 +1,160 @@
-// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \
-// RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefixes=CHECK \
-// RUN:   -DFNATTRS="noundef nofpclass(nan inf)" -DTARGET=dx
-// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \
-// RUN:   spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefixes=CHECK \
-// RUN:   -DFNATTRS="spir_func noundef nofpclass(nan inf)" -DTARGET=spv
-
-// CHECK-LABEL: test_lerp_double
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn float @llvm.[[TARGET]].lerp.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
-// CHECK: ret float %hlsl.lerp
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple  dxil-pc-shadermodel6.3-library %s -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK -DFNATTRS="noundef nofpclass(nan inf)" -DTARGET=dx
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple spirv-unknown-vulkan-compute %s -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK -DFNATTRS="spir_func noundef nofpclass(nan inf)" -DTARGET=spv
+
+// CHECK: define [[FNATTRS]] float @_Z16test_lerp_doubled(
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = fptrunc {{.*}} double [[P0:%.*]] to float
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} float @llvm.[[TARGET]].lerp.f32(float [[CONV]], float [[CONV]], float [[CONV]])
+// CHECK-NEXT:    ret float [[LERP]]
 float test_lerp_double(double p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_double2
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.[[TARGET]].lerp.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}})
-// CHECK: ret <2 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <2 x float> @_Z17test_lerp_double2Dv2_d(
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = fptrunc {{.*}} <2 x double> [[P0:%.*]] to <2 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <2 x float> @llvm.[[TARGET]].lerp.v2f32(<2 x float> [[CONV]], <2 x float> [[CONV]], <2 x float> [[CONV]])
+// CHECK-NEXT:    ret <2 x float> [[LERP]]
 float2 test_lerp_double2(double2 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_double3
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.[[TARGET]].lerp.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, <3 x float> %{{.*}})
-// CHECK: ret <3 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <3 x float> @_Z17test_lerp_double3Dv3_d(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = fptrunc {{.*}} <3 x double> [[P0:%.*]] to <3 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <3 x float> @llvm.[[TARGET]].lerp.v3f32(<3 x float> [[CONV]], <3 x float> [[CONV]], <3 x float> [[CONV]])
+// CHECK-NEXT:    ret <3 x float> [[LERP]]
+//
 float3 test_lerp_double3(double3 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_double4
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.[[TARGET]].lerp.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
-// CHECK: ret <4 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <4 x float> @_Z17test_lerp_double4Dv4_d(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = fptrunc {{.*}} <4 x double> [[P0:%.*]] to <4 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <4 x float> @llvm.[[TARGET]].lerp.v4f32(<4 x float> [[CONV]], <4 x float> [[CONV]], <4 x float> [[CONV]])
+// CHECK-NEXT:    ret <4 x float> [[LERP]]
+//
 float4 test_lerp_double4(double4 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_int
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn float @llvm.[[TARGET]].lerp.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
-// CHECK: ret float %hlsl.lerp
+// CHECK: define [[FNATTRS]] float @_Z13test_lerp_inti(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp i32 [[P0:%.*]] to float
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} float @llvm.[[TARGET]].lerp.f32(float [[CONV]], float [[CONV]], float [[CONV]])
+// CHECK-NEXT:    ret float [[LERP]]
+//
 float test_lerp_int(int p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_int2
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.[[TARGET]].lerp.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}})
-// CHECK: ret <2 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <2 x float> @_Z14test_lerp_int2Dv2_i(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp <2 x i32> [[P0:%.*]] to <2 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <2 x float> @llvm.[[TARGET]].lerp.v2f32(<2 x float> [[CONV]], <2 x float> [[CONV]], <2 x float> [[CONV]])
+// CHECK-NEXT:    ret <2 x float> [[LERP]]
+//
 float2 test_lerp_int2(int2 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_int3
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.[[TARGET]].lerp.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, <3 x float> %{{.*}})
-// CHECK: ret <3 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <3 x float> @_Z14test_lerp_int3Dv3_i(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp <3 x i32> [[P0:%.*]] to <3 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <3 x float> @llvm.[[TARGET]].lerp.v3f32(<3 x float> [[CONV]], <3 x float> [[CONV]], <3 x float> [[CONV]])
+// CHECK-NEXT:    ret <3 x float> [[LERP]]
+//
 float3 test_lerp_int3(int3 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_int4
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.[[TARGET]].lerp.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
-// CHECK: ret <4 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <4 x float> @_Z14test_lerp_int4Dv4_i(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp <4 x i32> [[P0:%.*]] to <4 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <4 x float> @llvm.[[TARGET]].lerp.v4f32(<4 x float> [[CONV]], <4 x float> [[CONV]], <4 x float> [[CONV]])
+// CHECK-NEXT:    ret <4 x float> [[LERP]]
+//
 float4 test_lerp_int4(int4 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_uint
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn float @llvm.[[TARGET]].lerp.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
-// CHECK: ret float %hlsl.lerp
+// CHECK: define [[FNATTRS]] float @_Z14test_lerp_uintj(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = uitofp i32 [[P0:%.*]] to float
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} float @llvm.[[TARGET]].lerp.f32(float [[CONV]], float [[CONV]], float [[CONV]])
+// CHECK-NEXT:    ret float [[LERP]]
+//
 float test_lerp_uint(uint p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_uint2
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.[[TARGET]].lerp.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}})
-// CHECK: ret <2 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <2 x float> @_Z15test_lerp_uint2Dv2_j(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = uitofp <2 x i32> [[P0:%.*]] to <2 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <2 x float> @llvm.[[TARGET]].lerp.v2f32(<2 x float> [[CONV]], <2 x float> [[CONV]], <2 x float> [[CONV]])
+// CHECK-NEXT:    ret <2 x float> [[LERP]]
+//
 float2 test_lerp_uint2(uint2 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_uint3
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.[[TARGET]].lerp.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, <3 x float> %{{.*}})
-// CHECK: ret <3 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <3 x float> @_Z15test_lerp_uint3Dv3_j(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = uitofp <3 x i32> [[P0:%.*]] to <3 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <3 x float> @llvm.[[TARGET]].lerp.v3f32(<3 x float> [[CONV]], <3 x float> [[CONV]], <3 x float> [[CONV]])
+// CHECK-NEXT:    ret <3 x float> [[LERP]]
+//
 float3 test_lerp_uint3(uint3 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_uint4
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.[[TARGET]].lerp.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
-// CHECK: ret <4 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <4 x float> @_Z15test_lerp_uint4Dv4_j(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = uitofp <4 x i32> [[P0:%.*]] to <4 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <4 x float> @llvm.[[TARGET]].lerp.v4f32(<4 x float> [[CONV]], <4 x float> [[CONV]], <4 x float> [[CONV]])
+// CHECK-NEXT:    ret <4 x float> [[LERP]]
+//
 float4 test_lerp_uint4(uint4 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_int64_t
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn float @llvm.[[TARGET]].lerp.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
-// CHECK: ret float %hlsl.lerp
+// CHECK: define [[FNATTRS]] float @_Z17test_lerp_int64_tl(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp i64 [[P0:%.*]] to float
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} float @llvm.[[TARGET]].lerp.f32(float [[CONV]], float [[CONV]], float [[CONV]])
+// CHECK-NEXT:    ret float [[LERP]]
+//
 float test_lerp_int64_t(int64_t p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_int64_t2
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.[[TARGET]].lerp.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}})
-// CHECK: ret <2 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <2 x float> @_Z18test_lerp_int64_t2Dv2_l(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp <2 x i64> [[P0:%.*]] to <2 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <2 x float> @llvm.[[TARGET]].lerp.v2f32(<2 x float> [[CONV]], <2 x float> [[CONV]], <2 x float> [[CONV]])
+// CHECK-NEXT:    ret <2 x float> [[LERP]]
+//
 float2 test_lerp_int64_t2(int64_t2 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_int64_t3
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.[[TARGET]].lerp.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, <3 x float> %{{.*}})
-// CHECK: ret <3 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <3 x float> @_Z18test_lerp_int64_t3Dv3_l(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp <3 x i64> [[P0:%.*]] to <3 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <3 x float> @llvm.[[TARGET]].lerp.v3f32(<3 x float> [[CONV]], <3 x float> [[CONV]], <3 x float> [[CONV]])
+// CHECK-NEXT:    ret <3 x float> [[LERP]]
+//
 float3 test_lerp_int64_t3(int64_t3 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_int64_t4
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.[[TARGET]].lerp.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
-// CHECK: ret <4 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <4 x float> @_Z18test_lerp_int64_t4Dv4_l(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp <4 x i64> [[P0:%.*]] to <4 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <4 x float> @llvm.[[TARGET]].lerp.v4f32(<4 x float> [[CONV]], <4 x float> [[CONV]], <4 x float> [[CONV]])
+// CHECK-NEXT:    ret <4 x float> [[LERP]]
+//
 float4 test_lerp_int64_t4(int64_t4 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_uint64_t
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn float @llvm.[[TARGET]].lerp.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
-// CHECK: ret float %hlsl.lerp
+// CHECK: define [[FNATTRS]] float @_Z18test_lerp_uint64_tm(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = uitofp i64 [[P0:%.*]] to float
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} float @llvm.[[TARGET]].lerp.f32(float [[CONV]], float [[CONV]], float [[CONV]])
+// CHECK-NEXT:    ret float [[LERP]]
+//
 float test_lerp_uint64_t(uint64_t p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_uint64_t2
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.[[TARGET]].lerp.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}})
-// CHECK: ret <2 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <2 x float> @_Z19test_lerp_uint64_t2Dv2_m(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = uitofp <2 x i64> [[P0:%.*]] to <2 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <2 x float> @llvm.[[TARGET]].lerp.v2f32(<2 x float> [[CONV]], <2 x float> [[CONV]], <2 x float> [[CONV]])
+// CHECK-NEXT:    ret <2 x float> [[LERP]]
+//
 float2 test_lerp_uint64_t2(uint64_t2 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_uint64_t3
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.[[TARGET]].lerp.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, <3 x float> %{{.*}})
-// CHECK: ret <3 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <3 x float> @_Z19test_lerp_uint64_t3Dv3_m(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = uitofp <3 x i64> [[P0:%.*]] to <3 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <3 x float> @llvm.[[TARGET]].lerp.v3f32(<3 x float> [[CONV]], <3 x float> [[CONV]], <3 x float> [[CONV]])
+// CHECK-NEXT:    ret <3 x float> [[LERP]]
+//
 float3 test_lerp_uint64_t3(uint64_t3 p0) { return lerp(p0, p0, p0); }
 
-// CHECK-LABEL: test_lerp_uint64_t4
-// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.[[TARGET]].lerp.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
-// CHECK: ret <4 x float> %hlsl.lerp
+// CHECK: define [[FNATTRS]] <4 x float> @_Z19test_lerp_uint64_t4Dv4_m(
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CONV:%.*]] = uitofp <4 x i64> [[P0:%.*]] to <4 x float>
+// CHECK-NEXT:    [[LERP:%.*]] = tail call {{.*}} <4 x float> @llvm.[[TARGET]].lerp.v4f32(<4 x float> [[CONV]], <4 x float> [[CONV]], <4 x float> [[CONV]])
+// CHECK-NEXT:    ret <4 x float> [[LERP]]
+//
 float4 test_lerp_uint64_t4(uint64_t4 p0) { return lerp(p0, p0, p0); }

// CHECK-LABEL: test_lerp_double
// CHECK: %hlsl.lerp = call reassoc nnan ninf nsz arcp afn float @llvm.[[TARGET]].lerp.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
// CHECK: ret float %hlsl.lerp
// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK -DFNATTRS="noundef nofpclass(nan inf)" -DTARGET=dx
Copy link
Member

@farzonl farzonl Apr 30, 2025

Choose a reason for hiding this comment

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

why do you need O1 for this you can check for fptrunc or uitofp without you just can't do CHECK-NEXT it would have to be all CHECK calls.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With -disable-llvm-passes we're testing IR that looks like this:

; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
define noundef nofpclass(nan inf) float @_Z16test_lerp_doubled(double noundef nofpclass(nan inf) %p0) #0 {
entry:
  %p0.addr = alloca double, align 8
  store double %p0, ptr %p0.addr, align 8
  %0 = load double, ptr %p0.addr, align 8
  %1 = load double, ptr %p0.addr, align 8
  %2 = load double, ptr %p0.addr, align 8
  %call = call reassoc nnan ninf nsz arcp afn noundef nofpclass(nan inf) float @_ZN4hlsl4lerpEddd(double noundef nofpclass(nan inf) %0, double noundef nofpclass(nan inf) %1, double noundef nofpclass(nan inf) %2) #2
  ret float %call
}

; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
define linkonce_odr noundef nofpclass(nan inf) float @_ZN4hlsl4lerpEddd(double noundef nofpclass(nan inf) %V1, double noundef nofpclass(nan inf) %V2, double noundef nofpclass(nan inf) %V3) #0 {
entry:
  %V1.addr = alloca double, align 8
  %V2.addr = alloca double, align 8
  %V3.addr = alloca double, align 8
  store double %V1, ptr %V1.addr, align 8
  store double %V2, ptr %V2.addr, align 8
  store double %V3, ptr %V3.addr, align 8
  %0 = load double, ptr %V1.addr, align 8
  %conv = fptrunc reassoc nnan ninf nsz arcp afn double %0 to float
  %1 = load double, ptr %V2.addr, align 8
  %conv1 = fptrunc reassoc nnan ninf nsz arcp afn double %1 to float
  %2 = load double, ptr %V3.addr, align 8
  %conv2 = fptrunc reassoc nnan ninf nsz arcp afn double %2 to float
  %hlsl.lerp = call reassoc nnan ninf nsz arcp afn float @llvm.dx.lerp.f32(float %conv, float %conv1, float %conv2)
  ret float %hlsl.lerp
}

The first check matched the start of the @_Z16test_lerp_doubled function, and the second check matched the second last instruction in @_ZN4hlsl4lerpEddd. This relies on the called function happening to come immediately after the caller, and of course it breaks if we have two tests that call the same overload. In this case we happened not to be.

Arguably, we could do -O0 instead and test the following:

define noundef nofpclass(nan inf) float @_Z16test_lerp_doubled(double noundef nofpclass(nan inf) %p0) #0 {
entry:
  %V1.addr.i = alloca double, align 8
  %V2.addr.i = alloca double, align 8
  %V3.addr.i = alloca double, align 8
  %p0.addr = alloca double, align 8
  store double %p0, ptr %p0.addr, align 8
  %0 = load double, ptr %p0.addr, align 8
  %1 = load double, ptr %p0.addr, align 8
  %2 = load double, ptr %p0.addr, align 8
  store double %0, ptr %V1.addr.i, align 8
  store double %1, ptr %V2.addr.i, align 8
  store double %2, ptr %V3.addr.i, align 8
  %3 = load double, ptr %V1.addr.i, align 8
  %conv.i = fptrunc reassoc nnan ninf nsz arcp afn double %3 to float
  %4 = load double, ptr %V2.addr.i, align 8
  %conv1.i = fptrunc reassoc nnan ninf nsz arcp afn double %4 to float
  %5 = load double, ptr %V3.addr.i, align 8
  %conv2.i = fptrunc reassoc nnan ninf nsz arcp afn double %5 to float
  %hlsl.lerp.i = call reassoc nnan ninf nsz arcp afn noundef float @llvm.dx.lerp.f32(float %conv.i, float %conv1.i, float %conv2.i)
  ret float %hlsl.lerp.i
}

In this case I could check for fptrunc. Of course, if I want to check that that fptrunc feeds to the call to lerp I need to check for 3 of them.

With -O1 we can write checks that this gives us precisely what we expect in a way that's easy to read, understand, and verify is correct.

Copy link
Member

@farzonl farzonl Apr 30, 2025

Choose a reason for hiding this comment

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

My concern is that we would have tests dependent on optimization level. I think in practice these are theoretical concerns but i’m going to make them anyway. First while unlikely this could obscure bugs in our implementation. I would want to confirm these test are correct before optimizations. Second while rare That could mean the next time someone changes what passes run as part of O1 that could change our tests.

We have been doing -O0 for other hlsl source dependent tests so we can take advantage of constexprs. I don’t know why that would be problematic here.

I need to check for 3 of them.

Why cant you just do a CHECK-COUNT?

Copy link
Contributor Author

@bogner bogner Apr 30, 2025

Choose a reason for hiding this comment

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

I mean, these tests are checking that a single function maps to a single intrinsic - unless we start adding passes that replace a target specific intrinsic with another I don't see what could possibly change here.

These are really tests that we have the right set of overloads, and that they map to the obvious implementation. Most, if not all, of the logic that's interesting for these tests is in Sema anyway. The only other kind of bug that these are likely to catch in practice is that we literally lower to the wrong operation. "If you pass in these arguments, it generates something sane - if you pass in those, it's an error".

I guess I'm fine with changing these to be -O0 tests, but that's mostly because I'm 100% convinced it doesn't matter. I definitely do not agree that those prove anything that these don't, and the tests are enough harder to read and write that I do think they're worse from the point of view of reviewability and understanding the code via the tests.

FWIW, it's incredibly prevalent in the clang CodeGen tests to use -O1 so that the tests are more readable (as the allocas for stack variables are just generally noisy):

$ grep -rho -- " -O[0-9]" clang/test/CodeGen*  | sort | uniq -c
    701  -O0
   1200  -O1
    522  -O2
    317  -O3

Why cant you just do a CHECK-COUNT?

Because you can't capture 3 patterns with CHECK-COUNT? As written, the tests pattern match the result of the fptrunc and make sure it's used in the call to the intrinsic. Since it's the same argument across the board, this keeps things concise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discussed offline with @farzonl - I've opted to switch this to -O0 to be consistent with many of the other hlsl builtins tests

@farzonl
Copy link
Member

farzonl commented Apr 30, 2025

I have a strong suspicion all the *-overload.hlsl tests have the same mistake and are also incorrect and need to updated. Can you file a ticket for investigating\cleaning up the other overload tests. Not work you have to do, but we should at least track that it needs ot be done.

@bogner
Copy link
Contributor Author

bogner commented Apr 30, 2025

I have a strong suspicion all the *-overload.hlsl tests have the same mistake and are also incorrect and need to updated. Can you file a ticket for investigating\cleaning up the other overload tests. Not work you have to do, but we should at least track that it needs ot be done.

#138016

@bogner bogner merged commit d851490 into llvm:main Apr 30, 2025
6 of 9 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Apr 30, 2025

LLVM Buildbot has detected a new failure on builder lldb-aarch64-ubuntu running on linaro-lldb-aarch64-ubuntu while building clang at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/16945

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: tools/lldb-server/TestGdbRemoteCompletion.py (1209 of 2154)
UNSUPPORTED: lldb-api :: tools/lldb-server/TestGdbRemoteFork.py (1210 of 2154)
UNSUPPORTED: lldb-api :: tools/lldb-server/TestGdbRemoteForkNonStop.py (1211 of 2154)
UNSUPPORTED: lldb-api :: tools/lldb-server/TestGdbRemoteForkResume.py (1212 of 2154)
PASS: lldb-api :: tools/lldb-server/TestGdbRemoteExitCode.py (1213 of 2154)
PASS: lldb-api :: terminal/TestEditline.py (1214 of 2154)
PASS: lldb-api :: tools/lldb-server/TestGdbRemoteHostInfo.py (1215 of 2154)
PASS: lldb-api :: tools/lldb-server/TestGdbRemoteModuleInfo.py (1216 of 2154)
PASS: lldb-api :: tools/lldb-server/TestGdbRemoteAuxvSupport.py (1217 of 2154)
UNRESOLVED: lldb-api :: tools/lldb-dap/variables/TestDAP_variables.py (1218 of 2154)
******************** TEST 'lldb-api :: tools/lldb-dap/variables/TestDAP_variables.py' FAILED ********************
Script:
--
/usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --arch aarch64 --build-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/tools/lldb-dap/variables -p TestDAP_variables.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision d851490c290832507d5fd87227e995d233b9f5b2)
  clang revision d851490c290832507d5fd87227e995d233b9f5b2
  llvm revision d851490c290832507d5fd87227e995d233b9f5b2
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_darwin_dwarf_missing_obj (TestDAP_variables.TestDAP_variables) (requires one of macosx, darwin, ios, tvos, watchos, bridgeos, iphonesimulator, watchsimulator, appletvsimulator) 
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_darwin_dwarf_missing_obj_with_symbol_ondemand_enabled (TestDAP_variables.TestDAP_variables) (requires one of macosx, darwin, ios, tvos, watchos, bridgeos, iphonesimulator, watchsimulator, appletvsimulator) 
========= DEBUG ADAPTER PROTOCOL LOGS =========
1746041839.157184362 --> (stdin/stdout) {"command":"initialize","type":"request","arguments":{"adapterID":"lldb-native","clientID":"vscode","columnsStartAt1":true,"linesStartAt1":true,"locale":"en-us","pathFormat":"path","supportsRunInTerminalRequest":true,"supportsVariablePaging":true,"supportsVariableType":true,"supportsStartDebuggingRequest":true,"supportsProgressReporting":true,"$__lldb_sourceInitFile":false},"seq":1}
1746041839.159280300 <-- (stdin/stdout) {"body":{"$__lldb_version":"lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision d851490c290832507d5fd87227e995d233b9f5b2)\n  clang revision d851490c290832507d5fd87227e995d233b9f5b2\n  llvm revision d851490c290832507d5fd87227e995d233b9f5b2","completionTriggerCharacters":["."," ","\t"],"exceptionBreakpointFilters":[{"default":false,"filter":"cpp_catch","label":"C++ Catch"},{"default":false,"filter":"cpp_throw","label":"C++ Throw"},{"default":false,"filter":"objc_catch","label":"Objective-C Catch"},{"default":false,"filter":"objc_throw","label":"Objective-C Throw"}],"supportTerminateDebuggee":true,"supportsBreakpointLocationsRequest":true,"supportsCancelRequest":true,"supportsCompletionsRequest":true,"supportsConditionalBreakpoints":true,"supportsConfigurationDoneRequest":true,"supportsDataBreakpoints":true,"supportsDelayedStackTraceLoading":true,"supportsDisassembleRequest":true,"supportsEvaluateForHovers":true,"supportsExceptionInfoRequest":true,"supportsExceptionOptions":true,"supportsFunctionBreakpoints":true,"supportsHitConditionalBreakpoints":true,"supportsInstructionBreakpoints":true,"supportsLogPoints":true,"supportsModulesRequest":true,"supportsReadMemoryRequest":true,"supportsRestartRequest":true,"supportsSetVariable":true,"supportsStepInTargetsRequest":true,"supportsSteppingGranularity":true,"supportsValueFormattingOptions":true},"command":"initialize","request_seq":1,"seq":0,"success":true,"type":"response"}
1746041839.159468889 --> (stdin/stdout) {"command":"launch","type":"request","arguments":{"program":"/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/tools/lldb-dap/variables/TestDAP_variables.test_indexedVariables/a.out","initCommands":["settings clear --all","settings set symbols.enable-external-lookup false","settings set target.inherit-tcc true","settings set target.disable-aslr false","settings set target.detach-on-error false","settings set target.auto-apply-fixits false","settings set plugin.process.gdb-remote.packet-timeout 60","settings set symbols.clang-modules-cache-path \"/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api\"","settings set use-color false","settings set show-statusline false"],"disableASLR":false,"enableAutoVariableSummaries":false,"enableSyntheticChildDebugging":false,"displayExtendedBacktrace":false},"seq":2}
1746041839.159664631 <-- (stdin/stdout) {"body":{"category":"console","output":"Running initCommands:\n"},"event":"output","seq":0,"type":"event"}
1746041839.159687281 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings clear --all\n"},"event":"output","seq":0,"type":"event"}
1746041839.159697056 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set symbols.enable-external-lookup false\n"},"event":"output","seq":0,"type":"event"}
1746041839.159705400 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set target.inherit-tcc true\n"},"event":"output","seq":0,"type":"event"}
1746041839.159713984 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set target.disable-aslr false\n"},"event":"output","seq":0,"type":"event"}
1746041839.159721613 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set target.detach-on-error false\n"},"event":"output","seq":0,"type":"event"}
1746041839.159729481 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set target.auto-apply-fixits false\n"},"event":"output","seq":0,"type":"event"}
1746041839.159737349 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set plugin.process.gdb-remote.packet-timeout 60\n"},"event":"output","seq":0,"type":"event"}
1746041839.159758568 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set symbols.clang-modules-cache-path \"/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api\"\n"},"event":"output","seq":0,"type":"event"}
1746041839.159776211 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set use-color false\n"},"event":"output","seq":0,"type":"event"}
1746041839.159784079 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set show-statusline false\n"},"event":"output","seq":0,"type":"event"}
1746041839.234522581 <-- (stdin/stdout) {"command":"launch","request_seq":2,"seq":0,"success":true,"type":"response"}
1746041839.234544992 <-- (stdin/stdout) {"body":{"module":{"addressRange":"281473825898496","id":"46771E9A-54FF-F825-3560-60BC1C8B4A44-C1108BF8","name":"ld-linux-aarch64.so.1","path":"/usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1","symbolStatus":"Symbols not found."},"reason":"new"},"event":"module","seq":0,"type":"event"}
1746041839.234567165 <-- (stdin/stdout) {"body":{"isLocalProcess":true,"name":"/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/tools/lldb-dap/variables/TestDAP_variables.test_indexedVariables/a.out","startMethod":"launch","systemProcessId":1336486},"event":"process","seq":0,"type":"event"}
1746041839.234577179 <-- (stdin/stdout) {"event":"initialized","seq":0,"type":"event"}
1746041839.234587908 <-- (stdin/stdout) {"body":{"module":{"addressRange":"281473826131968","id":"4A8F74F7-08C0-3C8C-B911-12040A09904C-51F3DA5C","name":"[vdso]","path":"[vdso]","symbolStatus":"Symbols not found."},"reason":"new"},"event":"module","seq":0,"type":"event"}

IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
These tests had checks across multiple functions, because none of the
hlsl header implementation functions were inlined. Switch the run lines
to use -O1 instead of -disable-llvm-passes and rewrite the tests to
actually look at the whole function.

Note - this would be simpler with update_cc_test_checks, but the
differences between DX and SPIRV are difficult to account for with those
scripts.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
These tests had checks across multiple functions, because none of the
hlsl header implementation functions were inlined. Switch the run lines
to use -O1 instead of -disable-llvm-passes and rewrite the tests to
actually look at the whole function.

Note - this would be simpler with update_cc_test_checks, but the
differences between DX and SPIRV are difficult to account for with those
scripts.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
These tests had checks across multiple functions, because none of the
hlsl header implementation functions were inlined. Switch the run lines
to use -O1 instead of -disable-llvm-passes and rewrite the tests to
actually look at the whole function.

Note - this would be simpler with update_cc_test_checks, but the
differences between DX and SPIRV are difficult to account for with those
scripts.
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
These tests had checks across multiple functions, because none of the
hlsl header implementation functions were inlined. Switch the run lines
to use -O1 instead of -disable-llvm-passes and rewrite the tests to
actually look at the whole function.

Note - this would be simpler with update_cc_test_checks, but the
differences between DX and SPIRV are difficult to account for with those
scripts.
Ankur-0429 pushed a commit to Ankur-0429/llvm-project that referenced this pull request May 9, 2025
These tests had checks across multiple functions, because none of the
hlsl header implementation functions were inlined. Switch the run lines
to use -O1 instead of -disable-llvm-passes and rewrite the tests to
actually look at the whole function.

Note - this would be simpler with update_cc_test_checks, but the
differences between DX and SPIRV are difficult to account for with those
scripts.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants