https://github.com/kmpeng created https://github.com/llvm/llvm-project/pull/216228
Closes #128043. This PR replaces the previous implementation of `normalize` with a new one inside the header files. It also adds the `__builtin_spirv_normalize` SPIR-V builtin (+ relevant tests) to use as a fast path in the header implementation so SPIR-V can still emit the GL/CL extension instructions. Assisted-by: Claude Opus 4.8 >From 02c5c0955b27aea6ea25f9b554314a39eddfa85f Mon Sep 17 00:00:00 2001 From: kmpeng <[email protected]> Date: Thu, 13 Aug 2026 18:49:05 -0700 Subject: [PATCH] move `normalize` implementation + add spirv builtin --- clang/include/clang/Basic/Builtins.td | 6 - .../clang/Basic/BuiltinsSPIRVCommon.td | 1 + clang/include/clang/Basic/HLSLIntrinsics.td | 3 +- clang/lib/CodeGen/CGHLSLBuiltins.cpp | 11 - clang/lib/CodeGen/CGHLSLRuntime.h | 1 - clang/lib/CodeGen/TargetBuiltins/SPIR.cpp | 8 + .../lib/Headers/hlsl/hlsl_intrinsic_helpers.h | 8 + clang/lib/Sema/SemaHLSL.cpp | 12 - clang/lib/Sema/SemaSPIRV.cpp | 17 ++ .../builtins/normalize-builtin.hlsl | 16 - .../builtins/normalize-overloads.hlsl | 278 ++++++++++++------ .../test/CodeGenHLSL/builtins/normalize.hlsl | 115 +++++--- clang/test/CodeGenSPIRV/Builtins/normalize.c | 41 +++ .../SemaHLSL/BuiltIns/normalize-errors.hlsl | 31 -- .../SemaSPIRV/BuiltIns/normalize-errors.c | 23 ++ llvm/include/llvm/IR/IntrinsicsDirectX.td | 1 - .../Target/DirectX/DXILIntrinsicExpansion.cpp | 41 --- llvm/test/CodeGen/DirectX/normalize.ll | 112 ------- llvm/test/CodeGen/DirectX/normalize_error.ll | 10 - .../SPIRV/hlsl-intrinsics/normalize.ll | 20 ++ llvm/test/CodeGen/SPIRV/opencl/normalize.ll | 52 ++++ 21 files changed, 429 insertions(+), 378 deletions(-) delete mode 100644 clang/test/CodeGenHLSL/builtins/normalize-builtin.hlsl create mode 100644 clang/test/CodeGenSPIRV/Builtins/normalize.c delete mode 100644 clang/test/SemaHLSL/BuiltIns/normalize-errors.hlsl create mode 100644 clang/test/SemaSPIRV/BuiltIns/normalize-errors.c delete mode 100644 llvm/test/CodeGen/DirectX/normalize.ll delete mode 100644 llvm/test/CodeGen/DirectX/normalize_error.ll create mode 100644 llvm/test/CodeGen/SPIRV/opencl/normalize.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 88aa8aee01e4b..9f7aa9bdb9571 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -5713,12 +5713,6 @@ def HLSLMul : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } -def HLSLNormalize : LangBuiltin<"HLSL_LANG"> { - let Spellings = ["__builtin_hlsl_normalize"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; - let Prototype = "void(...)"; -} - def HLSLTranspose : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_transpose"]; let Attributes = [NoThrow, Const, CustomTypeChecking]; diff --git a/clang/include/clang/Basic/BuiltinsSPIRVCommon.td b/clang/include/clang/Basic/BuiltinsSPIRVCommon.td index 448223a176ab4..91ad12599971f 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRVCommon.td +++ b/clang/include/clang/Basic/BuiltinsSPIRVCommon.td @@ -20,6 +20,7 @@ def subgroup_local_invocation_id : SPIRVBuiltin<"uint32_t()", [NoThrow, Const]>; def distance : SPIRVBuiltin<"void(...)", [NoThrow, Const]>; def length : SPIRVBuiltin<"void(...)", [NoThrow, Const]>; +def normalize : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>; def smoothstep : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>; def group_barrier : SPIRVBuiltin<"void()", [NoThrow]>; diff --git a/clang/include/clang/Basic/HLSLIntrinsics.td b/clang/include/clang/Basic/HLSLIntrinsics.td index fa5cb896e795a..91a542cf269e8 100644 --- a/clang/include/clang/Basic/HLSLIntrinsics.td +++ b/clang/include/clang/Basic/HLSLIntrinsics.td @@ -1284,7 +1284,7 @@ The return value is the \a I parameter. } // Returns the normalized unit vector of the specified floating-point vector. -def hlsl_normalize : HLSLOneArgBuiltin<"normalize", "__builtin_hlsl_normalize"> { +def hlsl_normalize : HLSLOneArgDetail<"normalize", "normalize_impl"> { let Doc = [{ \fn T normalize(T x) \brief Returns the normalized unit vector of the specified floating-point @@ -1293,6 +1293,7 @@ vector. Normalize is based on the following formula: x / length(x). }]; + let ParamNames = ["x"]; let VaryingTypes = [HalfTy, FloatTy]; let VaryingMatDims = []; } diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index 83c0bb2ac684b..38c2b58cea0c6 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -1137,17 +1137,6 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, CGM.getHLSLRuntime().getFirstBitLowIntrinsic(), ArrayRef<Value *>{X}, nullptr, "hlsl.firstbitlow"); } - case Builtin::BI__builtin_hlsl_normalize: { - Value *X = EmitScalarExpr(E->getArg(0)); - - assert(E->getArg(0)->getType()->hasFloatingRepresentation() && - "normalize operand must have a float representation"); - - return Builder.CreateIntrinsic( - /*ReturnType=*/X->getType(), - CGM.getHLSLRuntime().getNormalizeIntrinsic(), ArrayRef<Value *>{X}, - nullptr, "hlsl.normalize"); - } case Builtin::BI__builtin_hlsl_elementwise_f16tof32: { return handleElementwiseF16ToF32(*this, E); } diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 0b282f19cfcbc..a4ac00893c532 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -128,7 +128,6 @@ class CGHLSLRuntime { flattened_thread_id_in_group) GENERATE_HLSL_INTRINSIC_FUNCTION(IsInf, isinf) GENERATE_HLSL_INTRINSIC_FUNCTION(IsNaN, isnan) - GENERATE_HLSL_INTRINSIC_FUNCTION(Normalize, normalize) GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt) GENERATE_HLSL_INTRINSIC_FUNCTION(Saturate, saturate) GENERATE_HLSL_INTRINSIC_FUNCTION(Sign, sign) diff --git a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp index b2732e2ae674e..66f22d28e2a13 100644 --- a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp @@ -45,6 +45,14 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_length, ArrayRef<Value *>{X}, nullptr, "spv.length"); } + case SPIRV::BI__builtin_spirv_normalize: { + Value *X = EmitScalarExpr(E->getArg(0)); + assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + "normalize operand must have a float representation"); + return Builder.CreateIntrinsic( + /*ReturnType=*/X->getType(), Intrinsic::spv_normalize, + ArrayRef<Value *>{X}, nullptr, "spv.normalize"); + } case SPIRV::BI__builtin_spirv_reflect: { Value *I = EmitScalarExpr(E->getArg(0)); Value *N = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h index 977059a9fdae0..6d941231971c8 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h @@ -28,6 +28,14 @@ length_impl(vector<T, N> X) { #endif } +template <typename T> constexpr T normalize_impl(T X) { +#if (__has_builtin(__builtin_spirv_normalize)) + return __builtin_spirv_normalize(X); +#else + return X * rsqrt(dot(X, X)); +#endif +} + constexpr float dot2add_impl(half2 a, half2 b, float c) { #if (__has_builtin(__builtin_dx_dot2add)) return __builtin_dx_dot2add(a, b, c); diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 184339044e5bf..7eca8cae1f27e 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -4514,18 +4514,6 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { TheCall->setType(RetTy); break; } - case Builtin::BI__builtin_hlsl_normalize: { - if (SemaRef.checkArgCount(TheCall, 1)) - return true; - if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall, - CheckFloatOrHalfRepresentation)) - return true; - ExprResult A = TheCall->getArg(0); - QualType ArgTyA = A.get()->getType(); - // return type is the same as the input type - TheCall->setType(ArgTyA); - break; - } case Builtin::BI__builtin_elementwise_fma: { if (SemaRef.checkArgCount(TheCall, 3) || CheckAllArgsHaveSameType(&SemaRef, TheCall)) { diff --git a/clang/lib/Sema/SemaSPIRV.cpp b/clang/lib/Sema/SemaSPIRV.cpp index 8c2af5053bde2..7c1abcad17ac3 100644 --- a/clang/lib/Sema/SemaSPIRV.cpp +++ b/clang/lib/Sema/SemaSPIRV.cpp @@ -246,6 +246,23 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(const TargetInfo &TI, TheCall->setType(RetTy); break; } + case SPIRV::BI__builtin_spirv_normalize: { + if (SemaRef.checkArgCount(TheCall, 1)) + return true; + + ExprResult A = TheCall->getArg(0); + QualType ArgTyA = A.get()->getType(); + if (!ArgTyA->hasFloatingRepresentation()) { + SemaRef.Diag(A.get()->getBeginLoc(), diag::err_builtin_invalid_arg_type) + << /* ordinal */ 1 << /* scalar or vector */ 5 << /* no int */ 0 + << /* fp */ 1 << ArgTyA; + return true; + } + + QualType RetTy = ArgTyA; + TheCall->setType(RetTy); + break; + } case SPIRV::BI__builtin_spirv_reflect: { if (SemaRef.checkArgCount(TheCall, 2)) return true; diff --git a/clang/test/CodeGenHLSL/builtins/normalize-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/normalize-builtin.hlsl deleted file mode 100644 index 46bfb44c9b2a1..0000000000000 --- a/clang/test/CodeGenHLSL/builtins/normalize-builtin.hlsl +++ /dev/null @@ -1,16 +0,0 @@ -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -fnative-int16-type -emit-llvm -disable-llvm-passes -o - | FileCheck %s - - -// CHECK-LABEL: builtin_normalize_half -// CHECK: %hlsl.normalize = call reassoc nnan ninf nsz arcp afn half @llvm.dx.normalize.f16(half %{{.*}}) -// CHECK: ret half %hlsl.normalize -half builtin_normalize_half(half p0) { - return __builtin_hlsl_normalize(p0); -} - -// CHECK-LABEL: builtin_normalize_float -// CHECK: %hlsl.normalize = call reassoc nnan ninf nsz arcp afn float @llvm.dx.normalize.f32(float %{{.*}}) -// CHECK: ret float %hlsl.normalize -float builtin_normalize_float (float p0) { - return __builtin_hlsl_normalize(p0); -} diff --git a/clang/test/CodeGenHLSL/builtins/normalize-overloads.hlsl b/clang/test/CodeGenHLSL/builtins/normalize-overloads.hlsl index 8ed3ff26529d6..2256621892f04 100644 --- a/clang/test/CodeGenHLSL/builtins/normalize-overloads.hlsl +++ b/clang/test/CodeGenHLSL/builtins/normalize-overloads.hlsl @@ -1,199 +1,299 @@ // RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm \ -// RUN: -Wdeprecated-declarations -o - | FileCheck %s --check-prefixes=CHECK \ -// RUN: -DFNATTRS="hidden noundef nofpclass(nan inf)" -DTARGET=dx +// RUN: -Wdeprecated-declarations -o - | FileCheck %s --check-prefixes=CHECK,DXCHECK // RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \ // RUN: spirv-unknown-vulkan-library %s -emit-llvm \ -// RUN: -Wdeprecated-declarations -o - | FileCheck %s --check-prefixes=CHECK \ -// RUN: -DFNATTRS="hidden spir_func noundef nofpclass(nan inf)" -DTARGET=spv +// RUN: -Wdeprecated-declarations -o - | FileCheck %s --check-prefixes=CHECK,SPVCHECK // RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \ // RUN: -verify -verify-ignore-unexpected=note // RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple spirv-unknown-vulkan-library %s \ // RUN: -verify -verify-ignore-unexpected=note -// CHECK: define [[FNATTRS]] float @_Z21test_normalize_doubled( -// CHECK: [[CONVI:%.*]] = fptrunc {{.*}} double %{{.*}} to float -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} float @llvm.[[TARGET]].normalize.f32(float [[CONVI]]) -// CHECK: ret float [[HLSLNORMALIZEI]] +// CHECK-LABEL: test_normalize_double +// CHECK: [[CONVI:%.*]] = fptrunc {{.*}} double %{{.*}} to float +// DXCHECK: [[MUL:%.*]] = fmul {{.*}} float %{{.*}}, %{{.*}} +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[MUL]]) +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} float %{{.*}}, [[RSQRT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} float @llvm.spv.normalize.f32(float %{{.*}}) +// CHECK-NEXT: ret float [[RET]] float test_normalize_double(double p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x 64 bit API lowering for normalize is deprecated. Explicitly cast parameters to 32 or 16 bit types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <2 x float> @_Z22test_normalize_double2Dv2_d( -// CHECK: [[CONVI:%.*]] = fptrunc {{.*}} <2 x double> %{{.*}} to <2 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float> [[CONVI]]) -// CHECK: ret <2 x float> [[HLSLNORMALIZEI]] + +// CHECK-LABEL: test_normalize_double2 +// CHECK: [[CONVI:%.*]] = fptrunc {{.*}} <2 x double> %{{.*}} to <2 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x float> [[SPLATINSERT]], <2 x float> poison, <2 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <2 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <2 x float> @llvm.spv.normalize.v2f32(<2 x float> %{{.*}}) +// CHECK-NEXT: ret <2 x float> [[RET]] float2 test_normalize_double2(double2 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x 64 bit API lowering for normalize is deprecated. Explicitly cast parameters to 32 or 16 bit types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <3 x float> @_Z22test_normalize_double3Dv3_d( -// CHECK: [[CONVI:%.*]] = fptrunc {{.*}} <3 x double> %{{.*}} to <3 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <3 x float> @llvm.[[TARGET]].normalize.v3f32(<3 x float> [[CONVI]]) -// CHECK: ret <3 x float> [[HLSLNORMALIZEI]] + +// CHECK-LABEL: test_normalize_double3 +// CHECK: [[CONVI:%.*]] = fptrunc {{.*}} <3 x double> %{{.*}} to <3 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <3 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <3 x float> [[SPLATINSERT]], <3 x float> poison, <3 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <3 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <3 x float> @llvm.spv.normalize.v3f32(<3 x float> %{{.*}}) +// CHECK-NEXT: ret <3 x float> [[RET]] float3 test_normalize_double3(double3 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x 64 bit API lowering for normalize is deprecated. Explicitly cast parameters to 32 or 16 bit types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <4 x float> @_Z19test_length_double4Dv4_d( -// CHECK: [[CONVI:%.*]] = fptrunc {{.*}} <4 x double> %{{.*}} to <4 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <4 x float> @llvm.[[TARGET]].normalize.v4f32(<4 x float> [[CONVI]]) -// CHECK: ret <4 x float> [[HLSLNORMALIZEI]] -float4 test_length_double4(double4 p0) + +// CHECK-LABEL: test_normalize_double4 +// CHECK: [[CONVI:%.*]] = fptrunc {{.*}} <4 x double> %{{.*}} to <4 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x float> [[SPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <4 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <4 x float> @llvm.spv.normalize.v4f32(<4 x float> %{{.*}}) +// CHECK-NEXT: ret <4 x float> [[RET]] +float4 test_normalize_double4(double4 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x 64 bit API lowering for normalize is deprecated. Explicitly cast parameters to 32 or 16 bit types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] float @_Z18test_normalize_inti( -// CHECK: [[CONVI:%.*]] = sitofp {{.*}} i32 %{{.*}} to float -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} float @llvm.[[TARGET]].normalize.f32(float [[CONVI]]) -// CHECK: ret float [[HLSLNORMALIZEI]] +// CHECK-LABEL: test_normalize_int +// CHECK: [[CONVI:%.*]] = sitofp {{.*}} i32 %{{.*}} to float +// DXCHECK: [[MUL:%.*]] = fmul {{.*}} float %{{.*}}, %{{.*}} +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[MUL]]) +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} float %{{.*}}, [[RSQRT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} float @llvm.spv.normalize.f32(float %{{.*}}) +// CHECK-NEXT: ret float [[RET]] float test_normalize_int(int p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <2 x float> @_Z19test_normalize_int2Dv2_i( -// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <2 x i32> %{{.*}} to <2 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float> [[CONVI]]) -// CHECK: ret <2 x float> [[HLSLNORMALIZEI]] + +// CHECK-LABEL: test_normalize_int2 +// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <2 x i32> %{{.*}} to <2 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x float> [[SPLATINSERT]], <2 x float> poison, <2 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <2 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <2 x float> @llvm.spv.normalize.v2f32(<2 x float> %{{.*}}) +// CHECK-NEXT: ret <2 x float> [[RET]] float2 test_normalize_int2(int2 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <3 x float> @_Z19test_normalize_int3Dv3_i( -// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <3 x i32> %{{.*}} to <3 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <3 x float> @llvm.[[TARGET]].normalize.v3f32(<3 x float> [[CONVI]]) -// CHECK: ret <3 x float> [[HLSLNORMALIZEI]] + +// CHECK-LABEL: test_normalize_int3 +// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <3 x i32> %{{.*}} to <3 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <3 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <3 x float> [[SPLATINSERT]], <3 x float> poison, <3 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <3 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <3 x float> @llvm.spv.normalize.v3f32(<3 x float> %{{.*}}) +// CHECK-NEXT: ret <3 x float> [[RET]] float3 test_normalize_int3(int3 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <4 x float> @_Z16test_length_int4Dv4_i( -// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <4 x i32> %{{.*}} to <4 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <4 x float> @llvm.[[TARGET]].normalize.v4f32(<4 x float> [[CONVI]]) -// CHECK: ret <4 x float> [[HLSLNORMALIZEI]] -float4 test_length_int4(int4 p0) + +// CHECK-LABEL: test_normalize_int4 +// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <4 x i32> %{{.*}} to <4 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x float> [[SPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <4 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <4 x float> @llvm.spv.normalize.v4f32(<4 x float> %{{.*}}) +// CHECK-NEXT: ret <4 x float> [[RET]] +float4 test_normalize_int4(int4 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] float @_Z19test_normalize_uintj( -// CHECK: [[CONVI:%.*]] = uitofp {{.*}} i32 %{{.*}} to float -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} float @llvm.[[TARGET]].normalize.f32(float [[CONVI]]) -// CHECK: ret float [[HLSLNORMALIZEI]] +// CHECK-LABEL: test_normalize_uint +// CHECK: [[CONVI:%.*]] = uitofp {{.*}} i32 %{{.*}} to float +// DXCHECK: [[MUL:%.*]] = fmul {{.*}} float %{{.*}}, %{{.*}} +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[MUL]]) +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} float %{{.*}}, [[RSQRT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} float @llvm.spv.normalize.f32(float %{{.*}}) +// CHECK-NEXT: ret float [[RET]] float test_normalize_uint(uint p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <2 x float> @_Z20test_normalize_uint2Dv2_j( -// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <2 x i32> %{{.*}} to <2 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float> [[CONVI]]) -// CHECK: ret <2 x float> [[HLSLNORMALIZEI]] +// CHECK-LABEL: test_normalize_uint2 +// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <2 x i32> %{{.*}} to <2 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x float> [[SPLATINSERT]], <2 x float> poison, <2 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <2 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <2 x float> @llvm.spv.normalize.v2f32(<2 x float> %{{.*}}) +// CHECK-NEXT: ret <2 x float> [[RET]] float2 test_normalize_uint2(uint2 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <3 x float> @_Z20test_normalize_uint3Dv3_j( -// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <3 x i32> %{{.*}} to <3 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <3 x float> @llvm.[[TARGET]].normalize.v3f32(<3 x float> [[CONVI]]) -// CHECK: ret <3 x float> [[HLSLNORMALIZEI]] + +// CHECK-LABEL: test_normalize_uint3 +// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <3 x i32> %{{.*}} to <3 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <3 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <3 x float> [[SPLATINSERT]], <3 x float> poison, <3 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <3 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <3 x float> @llvm.spv.normalize.v3f32(<3 x float> %{{.*}}) +// CHECK-NEXT: ret <3 x float> [[RET]] float3 test_normalize_uint3(uint3 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <4 x float> @_Z17test_length_uint4Dv4_j( -// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <4 x i32> %{{.*}} to <4 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <4 x float> @llvm.[[TARGET]].normalize.v4f32(<4 x float> [[CONVI]]) -// CHECK: ret <4 x float> [[HLSLNORMALIZEI]] -float4 test_length_uint4(uint4 p0) + +// CHECK-LABEL: test_normalize_uint4 +// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <4 x i32> %{{.*}} to <4 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x float> [[SPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <4 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <4 x float> @llvm.spv.normalize.v4f32(<4 x float> %{{.*}}) +// CHECK-NEXT: ret <4 x float> [[RET]] +float4 test_normalize_uint4(uint4 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] float @_Z22test_normalize_int64_tl( -// CHECK: [[CONVI:%.*]] = sitofp {{.*}} i64 %{{.*}} to float -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} float @llvm.[[TARGET]].normalize.f32(float [[CONVI]]) -// CHECK: ret float [[HLSLNORMALIZEI]] +// CHECK-LABEL: test_normalize_int64_t +// CHECK: [[CONVI:%.*]] = sitofp {{.*}} i64 %{{.*}} to float +// DXCHECK: [[MUL:%.*]] = fmul {{.*}} float %{{.*}}, %{{.*}} +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[MUL]]) +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} float %{{.*}}, [[RSQRT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} float @llvm.spv.normalize.f32(float %{{.*}}) +// CHECK-NEXT: ret float [[RET]] float test_normalize_int64_t(int64_t p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <2 x float> @_Z23test_normalize_int64_t2Dv2_l( -// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <2 x i64> %{{.*}} to <2 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float> [[CONVI]]) -// CHECK: ret <2 x float> [[HLSLNORMALIZEI]] +// CHECK-LABEL: test_normalize_int64_t2 +// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <2 x i64> %{{.*}} to <2 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x float> [[SPLATINSERT]], <2 x float> poison, <2 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <2 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <2 x float> @llvm.spv.normalize.v2f32(<2 x float> %{{.*}}) +// CHECK-NEXT: ret <2 x float> [[RET]] float2 test_normalize_int64_t2(int64_t2 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <3 x float> @_Z23test_normalize_int64_t3Dv3_l( -// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <3 x i64> %{{.*}} to <3 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <3 x float> @llvm.[[TARGET]].normalize.v3f32(<3 x float> [[CONVI]]) -// CHECK: ret <3 x float> [[HLSLNORMALIZEI]] + +// CHECK-LABEL: test_normalize_int64_t3 +// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <3 x i64> %{{.*}} to <3 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <3 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <3 x float> [[SPLATINSERT]], <3 x float> poison, <3 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <3 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <3 x float> @llvm.spv.normalize.v3f32(<3 x float> %{{.*}}) +// CHECK-NEXT: ret <3 x float> [[RET]] float3 test_normalize_int64_t3(int64_t3 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <4 x float> @_Z20test_length_int64_t4Dv4_l( -// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <4 x i64> %{{.*}} to <4 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <4 x float> @llvm.[[TARGET]].normalize.v4f32(<4 x float> [[CONVI]]) -// CHECK: ret <4 x float> [[HLSLNORMALIZEI]] -float4 test_length_int64_t4(int64_t4 p0) + +// CHECK-LABEL: test_normalize_int64_t4 +// CHECK: [[CONVI:%.*]] = sitofp {{.*}} <4 x i64> %{{.*}} to <4 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x float> [[SPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <4 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <4 x float> @llvm.spv.normalize.v4f32(<4 x float> %{{.*}}) +// CHECK-NEXT: ret <4 x float> [[RET]] +float4 test_normalize_int64_t4(int64_t4 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] float @_Z23test_normalize_uint64_tm( -// CHECK: [[CONVI:%.*]] = uitofp {{.*}} i64 %{{.*}} to float -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} float @llvm.[[TARGET]].normalize.f32(float [[CONVI]]) -// CHECK: ret float [[HLSLNORMALIZEI]] +// CHECK-LABEL: test_normalize_uint64_t +// CHECK: [[CONVI:%.*]] = uitofp {{.*}} i64 %{{.*}} to float +// DXCHECK: [[MUL:%.*]] = fmul {{.*}} float %{{.*}}, %{{.*}} +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[MUL]]) +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} float %{{.*}}, [[RSQRT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} float @llvm.spv.normalize.f32(float %{{.*}}) +// CHECK-NEXT: ret float [[RET]] float test_normalize_uint64_t(uint64_t p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <2 x float> @_Z24test_normalize_uint64_t2Dv2_m( -// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <2 x i64> %{{.*}} to <2 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float> [[CONVI]]) -// CHECK: ret <2 x float> [[HLSLNORMALIZEI]] +// CHECK-LABEL: test_normalize_uint64_t2 +// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <2 x i64> %{{.*}} to <2 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x float> [[SPLATINSERT]], <2 x float> poison, <2 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <2 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <2 x float> @llvm.spv.normalize.v2f32(<2 x float> %{{.*}}) +// CHECK-NEXT: ret <2 x float> [[RET]] float2 test_normalize_uint64_t2(uint64_t2 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <3 x float> @_Z24test_normalize_uint64_t3Dv3_m( -// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <3 x i64> %{{.*}} to <3 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <3 x float> @llvm.[[TARGET]].normalize.v3f32(<3 x float> [[CONVI]]) -// CHECK: ret <3 x float> [[HLSLNORMALIZEI]] + +// CHECK-LABEL: test_normalize_uint64_t3 +// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <3 x i64> %{{.*}} to <3 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <3 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <3 x float> [[SPLATINSERT]], <3 x float> poison, <3 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <3 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <3 x float> @llvm.spv.normalize.v3f32(<3 x float> %{{.*}}) +// CHECK-NEXT: ret <3 x float> [[RET]] float3 test_normalize_uint64_t3(uint64_t3 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); } -// CHECK: define [[FNATTRS]] <4 x float> @_Z21test_length_uint64_t4Dv4_m( -// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <4 x i64> %{{.*}} to <4 x float> -// CHECK: [[HLSLNORMALIZEI:%.*]] = call {{.*}} <4 x float> @llvm.[[TARGET]].normalize.v4f32(<4 x float> [[CONVI]]) -// CHECK: ret <4 x float> [[HLSLNORMALIZEI]] -float4 test_length_uint64_t4(uint64_t4 p0) + +// CHECK-LABEL: test_normalize_uint64_t4 +// CHECK: [[CONVI:%.*]] = uitofp {{.*}} <4 x i64> %{{.*}} to <4 x float> +// DXCHECK: [[DOT:%.*]] = call {{.*}} float @llvm.dx.fdot.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call {{.*}} float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x float> [[SPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul {{.*}} <4 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call {{.*}} <4 x float> @llvm.spv.normalize.v4f32(<4 x float> %{{.*}}) +// CHECK-NEXT: ret <4 x float> [[RET]] +float4 test_normalize_uint64_t4(uint64_t4 p0) { // expected-warning@+1 {{'normalize' is deprecated: In 202x int lowering for normalize is deprecated. Explicitly cast parameters to float types.}} return normalize(p0); diff --git a/clang/test/CodeGenHLSL/builtins/normalize.hlsl b/clang/test/CodeGenHLSL/builtins/normalize.hlsl index d40feede9cca6..5d10e94fd692c 100644 --- a/clang/test/CodeGenHLSL/builtins/normalize.hlsl +++ b/clang/test/CodeGenHLSL/builtins/normalize.hlsl @@ -1,85 +1,106 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type -fnative-int16-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF \ -// RUN: -DFNATTRS="hidden noundef nofpclass(nan inf)" -DTARGET=dx -// RUN: %clang_cc1 -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,NO_HALF \ -// RUN: -DFNATTRS="hidden noundef nofpclass(nan inf)" -DTARGET=dx +// RUN: -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,DXCHECK // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ // RUN: spirv-unknown-vulkan-library %s -fnative-half-type -fnative-int16-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF \ -// RUN: -DFNATTRS="hidden spir_func noundef nofpclass(nan inf)" -DTARGET=spv -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: spirv-unknown-vulkan-library %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ -// RUN: -DFNATTRS="hidden spir_func noundef nofpclass(nan inf)" -DTARGET=spv +// RUN: -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPVCHECK -// NATIVE_HALF: define [[FNATTRS]] half @ -// NATIVE_HALF: call reassoc nnan ninf nsz arcp afn half @llvm.[[TARGET]].normalize.f16(half -// NO_HALF: call reassoc nnan ninf nsz arcp afn float @llvm.[[TARGET]].normalize.f32(float -// NATIVE_HALF: ret half -// NO_HALF: ret float +// CHECK-LABEL: test_normalize_half +// DXCHECK: [[DOT:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}} +// DXCHECK-NEXT: [[RSQRT:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.dx.rsqrt.f16(half [[DOT]]) +// DXCHECK-NEXT: [[RET:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, [[RSQRT]] +// SPVCHECK: [[RET:%.*]] = call reassoc nnan ninf nsz arcp afn noundef nofpclass(nan inf) half @llvm.spv.normalize.f16(half %{{.*}}) +// CHECK-NEXT: ret half [[RET]] half test_normalize_half(half p0) { return normalize(p0); } -// NATIVE_HALF: define [[FNATTRS]] <2 x half> @ -// NATIVE_HALF: call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.[[TARGET]].normalize.v2f16(<2 x half> -// NO_HALF: call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float> -// NATIVE_HALF: ret <2 x half> %hlsl.normalize -// NO_HALF: ret <2 x float> %hlsl.normalize + +// CHECK-LABEL: test_normalize_half2 +// DXCHECK: [[DOT:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.dx.rsqrt.f16(half [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x half> poison, half [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x half> [[SPLATINSERT]], <2 x half> poison, <2 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x half> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call reassoc nnan ninf nsz arcp afn noundef nofpclass(nan inf) <2 x half> @llvm.spv.normalize.v2f16(<2 x half> %{{.*}}) +// CHECK-NEXT: ret <2 x half> [[RET]] half2 test_normalize_half2(half2 p0) { return normalize(p0); } -// NATIVE_HALF: define [[FNATTRS]] <3 x half> @ -// NATIVE_HALF: call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.[[TARGET]].normalize.v3f16(<3 x half> -// NO_HALF: call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.[[TARGET]].normalize.v3f32(<3 x float> -// NATIVE_HALF: ret <3 x half> %hlsl.normalize -// NO_HALF: ret <3 x float> %hlsl.normalize + +// CHECK-LABEL: test_normalize_half3 +// DXCHECK: [[DOT:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v3f16(<3 x half> %{{.*}}, <3 x half> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.dx.rsqrt.f16(half [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <3 x half> poison, half [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <3 x half> [[SPLATINSERT]], <3 x half> poison, <3 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x half> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call reassoc nnan ninf nsz arcp afn noundef nofpclass(nan inf) <3 x half> @llvm.spv.normalize.v3f16(<3 x half> %{{.*}}) +// CHECK-NEXT: ret <3 x half> [[RET]] half3 test_normalize_half3(half3 p0) { return normalize(p0); } -// NATIVE_HALF: define [[FNATTRS]] <4 x half> @ -// NATIVE_HALF: call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.[[TARGET]].normalize.v4f16(<4 x half> -// NO_HALF: call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.[[TARGET]].normalize.v4f32(<4 x float> -// NATIVE_HALF: ret <4 x half> %hlsl.normalize -// NO_HALF: ret <4 x float> %hlsl.normalize + +// CHECK-LABEL: test_normalize_half4 +// DXCHECK: [[DOT:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v4f16(<4 x half> %{{.*}}, <4 x half> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.dx.rsqrt.f16(half [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <4 x half> poison, half [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x half> [[SPLATINSERT]], <4 x half> poison, <4 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x half> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call reassoc nnan ninf nsz arcp afn noundef nofpclass(nan inf) <4 x half> @llvm.spv.normalize.v4f16(<4 x half> %{{.*}}) +// CHECK-NEXT: ret <4 x half> [[RET]] half4 test_normalize_half4(half4 p0) { return normalize(p0); } -// CHECK: define [[FNATTRS]] float @ -// CHECK: call reassoc nnan ninf nsz arcp afn float @llvm.[[TARGET]].normalize.f32(float -// CHECK: ret float +// CHECK-LABEL: test_normalize_float +// DXCHECK: [[DOT:%.*]] = fmul reassoc nnan ninf nsz arcp afn float %{{.*}}, %{{.*}} +// DXCHECK-NEXT: [[RSQRT:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[RET:%.*]] = fmul reassoc nnan ninf nsz arcp afn float %{{.*}}, [[RSQRT]] +// SPVCHECK: [[RET:%.*]] = call reassoc nnan ninf nsz arcp afn noundef nofpclass(nan inf) float @llvm.spv.normalize.f32(float %{{.*}}) +// CHECK-NEXT: ret float [[RET]] float test_normalize_float(float p0) { return normalize(p0); } -// CHECK: define [[FNATTRS]] <2 x float> @ -// CHECK: %hlsl.normalize = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float> -// CHECK: ret <2 x float> %hlsl.normalize +// CHECK-LABEL: test_normalize_float2 +// DXCHECK: [[DOT:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <2 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x float> [[SPLATINSERT]], <2 x float> poison, <2 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call reassoc nnan ninf nsz arcp afn noundef nofpclass(nan inf) <2 x float> @llvm.spv.normalize.v2f32(<2 x float> %{{.*}}) +// CHECK-NEXT: ret <2 x float> [[RET]] float2 test_normalize_float2(float2 p0) { return normalize(p0); } -// CHECK: define [[FNATTRS]] <3 x float> @ -// CHECK: %hlsl.normalize = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.[[TARGET]].normalize.v3f32( -// CHECK: ret <3 x float> %hlsl.normalize + +// CHECK-LABEL: test_normalize_float3 +// DXCHECK: [[DOT:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <3 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <3 x float> [[SPLATINSERT]], <3 x float> poison, <3 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call reassoc nnan ninf nsz arcp afn noundef nofpclass(nan inf) <3 x float> @llvm.spv.normalize.v3f32(<3 x float> %{{.*}}) +// CHECK-NEXT: ret <3 x float> [[RET]] float3 test_normalize_float3(float3 p0) { return normalize(p0); } -// CHECK: define [[FNATTRS]] <4 x float> @ -// CHECK: %hlsl.normalize = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.[[TARGET]].normalize.v4f32( -// CHECK: ret <4 x float> %hlsl.normalize -float4 test_length_float4(float4 p0) + +// CHECK-LABEL: test_normalize_float4 +// DXCHECK: [[DOT:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}) +// DXCHECK-NEXT: [[RSQRT:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.rsqrt.f32(float [[DOT]]) +// DXCHECK-NEXT: [[SPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[RSQRT]], i64 0 +// DXCHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x float> [[SPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer +// DXCHECK-NEXT: [[RET:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> %{{.*}}, [[SPLAT]] +// SPVCHECK: [[RET:%.*]] = call reassoc nnan ninf nsz arcp afn noundef nofpclass(nan inf) <4 x float> @llvm.spv.normalize.v4f32(<4 x float> %{{.*}}) +// CHECK-NEXT: ret <4 x float> [[RET]] +float4 test_normalize_float4(float4 p0) { return normalize(p0); } diff --git a/clang/test/CodeGenSPIRV/Builtins/normalize.c b/clang/test/CodeGenSPIRV/Builtins/normalize.c new file mode 100644 index 0000000000000..87640cb33e19e --- /dev/null +++ b/clang/test/CodeGenSPIRV/Builtins/normalize.c @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -O1 -triple spirv-pc-vulkan-compute %s -emit-llvm -o - | FileCheck %s + +typedef _Float16 half; +typedef half half2 __attribute__((ext_vector_type(2))); +typedef half half3 __attribute__((ext_vector_type(3))); +typedef half half4 __attribute__((ext_vector_type(4))); +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float3 __attribute__((ext_vector_type(3))); +typedef float float4 __attribute__((ext_vector_type(4))); + +// CHECK: [[NORM:%.*]] = tail call half @llvm.spv.normalize.f16(half {{%.*}}) +// CHECK: ret half [[NORM]] +half test_normalize_half(half X) { return __builtin_spirv_normalize(X); } + +// CHECK: [[NORM:%.*]] = tail call <2 x half> @llvm.spv.normalize.v2f16(<2 x half> {{%.*}}) +// CHECK: ret <2 x half> [[NORM]] +half2 test_normalize_half2(half2 X) { return __builtin_spirv_normalize(X); } + +// CHECK: [[NORM:%.*]] = tail call <3 x half> @llvm.spv.normalize.v3f16(<3 x half> {{%.*}}) +// CHECK: ret <3 x half> [[NORM]] +half3 test_normalize_half3(half3 X) { return __builtin_spirv_normalize(X); } + +// CHECK: [[NORM:%.*]] = tail call <4 x half> @llvm.spv.normalize.v4f16(<4 x half> {{%.*}}) +// CHECK: ret <4 x half> [[NORM]] +half4 test_normalize_half4(half4 X) { return __builtin_spirv_normalize(X); } + +// CHECK: [[NORM:%.*]] = tail call float @llvm.spv.normalize.f32(float {{%.*}}) +// CHECK: ret float [[NORM]] +float test_normalize_float(float X) { return __builtin_spirv_normalize(X); } + +// CHECK: [[NORM:%.*]] = tail call <2 x float> @llvm.spv.normalize.v2f32(<2 x float> {{%.*}}) +// CHECK: ret <2 x float> [[NORM]] +float2 test_normalize_float2(float2 X) { return __builtin_spirv_normalize(X); } + +// CHECK: [[NORM:%.*]] = tail call <3 x float> @llvm.spv.normalize.v3f32(<3 x float> {{%.*}}) +// CHECK: ret <3 x float> [[NORM]] +float3 test_normalize_float3(float3 X) { return __builtin_spirv_normalize(X); } + +// CHECK: [[NORM:%.*]] = tail call <4 x float> @llvm.spv.normalize.v4f32(<4 x float> {{%.*}}) +// CHECK: ret <4 x float> [[NORM]] +float4 test_normalize_float4(float4 X) { return __builtin_spirv_normalize(X); } diff --git a/clang/test/SemaHLSL/BuiltIns/normalize-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/normalize-errors.hlsl deleted file mode 100644 index 377c2d5e41a73..0000000000000 --- a/clang/test/SemaHLSL/BuiltIns/normalize-errors.hlsl +++ /dev/null @@ -1,31 +0,0 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -disable-llvm-passes -verify - -void test_too_few_arg() -{ - return __builtin_hlsl_normalize(); - // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} -} - -void test_too_many_arg(float2 p0) -{ - return __builtin_hlsl_normalize(p0, p0); - // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} -} - -bool builtin_bool_to_float_type_promotion(bool p1) -{ - return __builtin_hlsl_normalize(p1); - // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'bool')}} -} - -bool builtin_normalize_int_to_float_promotion(int p1) -{ - return __builtin_hlsl_normalize(p1); - // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}} -} - -bool2 builtin_normalize_int2_to_float2_promotion(int2 p1) -{ - return __builtin_hlsl_normalize(p1); - // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int2' (aka 'vector<int, 2>'))}} -} diff --git a/clang/test/SemaSPIRV/BuiltIns/normalize-errors.c b/clang/test/SemaSPIRV/BuiltIns/normalize-errors.c new file mode 100644 index 0000000000000..7159bc8735279 --- /dev/null +++ b/clang/test/SemaSPIRV/BuiltIns/normalize-errors.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 %s -triple spirv-pc-vulkan-compute -verify + +typedef float float2 __attribute__((ext_vector_type(2))); + +void test_too_few_arg() { + return __builtin_spirv_normalize(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} +} + +float test_too_many_arg(float p0) { + return __builtin_spirv_normalize(p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} +} + +float test_int_scalar_inputs(int p0) { + return __builtin_spirv_normalize(p0); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int')}} +} + +float test_mismatched_return(float2 p0) { + return __builtin_spirv_normalize(p0); + // expected-error@-1 {{returning 'float2' (vector of 2 'float' values) from a function with incompatible result type 'float'}} +} diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index 9c9b2032035e3..4b895c1cfc8e9 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -255,7 +255,6 @@ def int_dx_legacyf32tof16 : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0 def int_dx_imad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrTriviallyScalarizable]>; def int_dx_umad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrTriviallyScalarizable]>; -def int_dx_normalize : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; def int_dx_wave_prefix_bit_count : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i1_ty], [IntrConvergent, IntrNoMem]>; def int_dx_rsqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrTriviallyScalarizable]>; def int_dx_wave_active_countbits : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i1_ty], [IntrConvergent, IntrNoMem]>; diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp index 8ecc7ddc4b64f..6ae641a5f2a03 100644 --- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -218,7 +218,6 @@ static bool isIntrinsicExpansion(Function &F) { case Intrinsic::dx_nclamp: case Intrinsic::dx_isinf: case Intrinsic::dx_isnan: - case Intrinsic::dx_normalize: case Intrinsic::dx_fdot: case Intrinsic::dx_sdot: case Intrinsic::dx_udot: @@ -625,43 +624,6 @@ static Value *expandLog10Intrinsic(CallInst *Orig) { return expandLogIntrinsic(Orig, numbers::ln2f / numbers::ln10f); } -// Use dot product of vector operand with itself to calculate the length. -// Divide the vector by that length to normalize it. -static Value *expandNormalizeIntrinsic(CallInst *Orig) { - Value *X = Orig->getOperand(0); - Type *Ty = Orig->getType(); - Type *EltTy = Ty->getScalarType(); - IRBuilder<> Builder(Orig); - - auto *XVec = dyn_cast<FixedVectorType>(Ty); - if (!XVec) { - if (auto *constantFP = dyn_cast<ConstantFP>(X)) { - const APFloat &fpVal = constantFP->getValueAPF(); - if (fpVal.isZero()) - reportFatalUsageError("Invalid input scalar: length is zero"); - } - return Builder.CreateFDiv(X, X); - } - - Value *DotProduct = expandFloatDotIntrinsic(Orig, X, X); - - // verify that the length is non-zero - // (if the dot product is non-zero, then the length is non-zero) - if (auto *constantFP = dyn_cast<ConstantFP>(DotProduct)) { - const APFloat &fpVal = constantFP->getValueAPF(); - if (fpVal.isZero()) - reportFatalUsageError("Invalid input vector: length is zero"); - } - - Value *Multiplicand = Builder.CreateIntrinsic(EltTy, Intrinsic::dx_rsqrt, - ArrayRef<Value *>{DotProduct}, - nullptr, "dx.rsqrt"); - - Value *MultiplicandVec = - Builder.CreateVectorSplat(XVec->getNumElements(), Multiplicand); - return Builder.CreateFMul(X, MultiplicandVec); -} - static Value *expandAtan2Intrinsic(CallInst *Orig) { Value *Y = Orig->getOperand(0); Value *X = Orig->getOperand(1); @@ -1286,9 +1248,6 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) { case Intrinsic::dx_isnan: Result = expand16BitIsNaN(Orig); break; - case Intrinsic::dx_normalize: - Result = expandNormalizeIntrinsic(Orig); - break; case Intrinsic::dx_fdot: Result = expandFloatDotIntrinsic(Orig); break; diff --git a/llvm/test/CodeGen/DirectX/normalize.ll b/llvm/test/CodeGen/DirectX/normalize.ll deleted file mode 100644 index db4a4900c0532..0000000000000 --- a/llvm/test/CodeGen/DirectX/normalize.ll +++ /dev/null @@ -1,112 +0,0 @@ -; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK -; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK - -; Make sure dxil operation function calls for normalize are generated for half/float. - -declare half @llvm.dx.normalize.f16(half) -declare <2 x half> @llvm.dx.normalize.v2f16(<2 x half>) -declare <3 x half> @llvm.dx.normalize.v3f16(<3 x half>) -declare <4 x half> @llvm.dx.normalize.v4f16(<4 x half>) - -declare float @llvm.dx.normalize.f32(float) -declare <2 x float> @llvm.dx.normalize.v2f32(<2 x float>) -declare <3 x float> @llvm.dx.normalize.v3f32(<3 x float>) -declare <4 x float> @llvm.dx.normalize.v4f32(<4 x float>) - -define noundef half @test_normalize_half(half noundef %p0) { -entry: - ; CHECK: fdiv half %p0, %p0 - %hlsl.normalize = call half @llvm.dx.normalize.f16(half %p0) - ret half %hlsl.normalize -} - -define noundef <2 x half> @test_normalize_half2(<2 x half> noundef %p0) { -entry: - ; EXPCHECK: [[doth2:%.*]] = call half @llvm.dx.dot2.f16(half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}) - ; DOPCHECK: [[doth2:%.*]] = call half @dx.op.dot2.f16(i32 54, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}) - ; EXPCHECK: [[rsqrt:%.*]] = call half @llvm.dx.rsqrt.f16(half [[doth2]]) - ; DOPCHECK: [[rsqrt:%.*]] = call half @dx.op.unary.f16(i32 25, half [[doth2]]) - ; CHECK: [[splatinserth2:%.*]] = insertelement <2 x half> poison, half [[rsqrt]], i64 0 - ; CHECK: [[splat:%.*]] = shufflevector <2 x half> [[splatinserth2]], <2 x half> poison, <2 x i32> zeroinitializer - ; CHECK: fmul <2 x half> %p0, [[splat]] - - %hlsl.normalize = call <2 x half> @llvm.dx.normalize.v2f16(<2 x half> %p0) - ret <2 x half> %hlsl.normalize -} - -define noundef <3 x half> @test_normalize_half3(<3 x half> noundef %p0) { -entry: - ; EXPCHECK: [[doth3:%.*]] = call half @llvm.dx.dot3.f16(half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}) - ; DOPCHECK: [[doth3:%.*]] = call half @dx.op.dot3.f16(i32 55, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}) - ; EXPCHECK: [[rsqrt:%.*]] = call half @llvm.dx.rsqrt.f16(half [[doth3]]) - ; DOPCHECK: [[rsqrt:%.*]] = call half @dx.op.unary.f16(i32 25, half [[doth3]]) - ; CHECK: [[splatinserth3:%.*]] = insertelement <3 x half> poison, half [[rsqrt]], i64 0 - ; CHECK: [[splat:%.*]] shufflevector <3 x half> [[splatinserth3]], <3 x half> poison, <3 x i32> zeroinitializer - ; CHECK: fmul <3 x half> %p0, %.splat - - %hlsl.normalize = call <3 x half> @llvm.dx.normalize.v3f16(<3 x half> %p0) - ret <3 x half> %hlsl.normalize -} - -define noundef <4 x half> @test_normalize_half4(<4 x half> noundef %p0) { -entry: - ; EXPCHECK: [[doth4:%.*]] = call half @llvm.dx.dot4.f16(half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}) - ; DOPCHECK: [[doth4:%.*]] = call half @dx.op.dot4.f16(i32 56, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}) - ; EXPCHECK: [[rsqrt:%.*]] = call half @llvm.dx.rsqrt.f16(half [[doth4]]) - ; DOPCHECK: [[rsqrt:%.*]] = call half @dx.op.unary.f16(i32 25, half [[doth4]]) - ; CHECK: [[splatinserth4:%.*]] = insertelement <4 x half> poison, half [[rsqrt]], i64 0 - ; CHECK: [[splat:%.*]] shufflevector <4 x half> [[splatinserth4]], <4 x half> poison, <4 x i32> zeroinitializer - ; CHECK: fmul <4 x half> %p0, %.splat - - %hlsl.normalize = call <4 x half> @llvm.dx.normalize.v4f16(<4 x half> %p0) - ret <4 x half> %hlsl.normalize -} - -define noundef float @test_normalize_float(float noundef %p0) { -entry: - ; CHECK: fdiv float %p0, %p0 - %hlsl.normalize = call float @llvm.dx.normalize.f32(float %p0) - ret float %hlsl.normalize -} - -define noundef <2 x float> @test_normalize_float2(<2 x float> noundef %p0) { -entry: - ; EXPCHECK: [[dotf2:%.*]] = call float @llvm.dx.dot2.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}) - ; DOPCHECK: [[dotf2:%.*]] = call float @dx.op.dot2.f32(i32 54, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}) - ; EXPCHECK: [[rsqrt:%.*]] = call float @llvm.dx.rsqrt.f32(float [[dotf2]]) - ; DOPCHECK: [[rsqrt:%.*]] = call float @dx.op.unary.f32(i32 25, float [[dotf2]]) - ; CHECK: [[splatinsertf2:%.*]] = insertelement <2 x float> poison, float [[rsqrt]], i64 0 - ; CHECK: [[splat:%.*]] shufflevector <2 x float> [[splatinsertf2]], <2 x float> poison, <2 x i32> zeroinitializer - ; CHECK: fmul <2 x float> %p0, %.splat - - %hlsl.normalize = call <2 x float> @llvm.dx.normalize.v2f32(<2 x float> %p0) - ret <2 x float> %hlsl.normalize -} - -define noundef <3 x float> @test_normalize_float3(<3 x float> noundef %p0) { -entry: - ; EXPCHECK: [[dotf3:%.*]] = call float @llvm.dx.dot3.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}) - ; DOPCHECK: [[dotf3:%.*]] = call float @dx.op.dot3.f32(i32 55, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}) - ; EXPCHECK: [[rsqrt:%.*]] = call float @llvm.dx.rsqrt.f32(float [[dotf3]]) - ; DOPCHECK: [[rsqrt:%.*]] = call float @dx.op.unary.f32(i32 25, float [[dotf3]]) - ; CHECK: [[splatinsertf3:%.*]] = insertelement <3 x float> poison, float [[rsqrt]], i64 0 - ; CHECK: [[splat:%.*]] shufflevector <3 x float> [[splatinsertf3]], <3 x float> poison, <3 x i32> zeroinitializer - ; CHECK: fmul <3 x float> %p0, %.splat - - %hlsl.normalize = call <3 x float> @llvm.dx.normalize.v3f32(<3 x float> %p0) - ret <3 x float> %hlsl.normalize -} - -define noundef <4 x float> @test_normalize_float4(<4 x float> noundef %p0) { -entry: - ; EXPCHECK: [[dotf4:%.*]] = call float @llvm.dx.dot4.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}) - ; DOPCHECK: [[dotf4:%.*]] = call float @dx.op.dot4.f32(i32 56, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}) - ; EXPCHECK: [[rsqrt:%.*]] = call float @llvm.dx.rsqrt.f32(float [[dotf4]]) - ; DOPCHECK: [[rsqrt:%.*]] = call float @dx.op.unary.f32(i32 25, float [[dotf4]]) - ; CHECK: [[splatinsertf4:%.*]] = insertelement <4 x float> poison, float [[rsqrt]], i64 0 - ; CHECK: [[splat:%.*]] shufflevector <4 x float> [[splatinsertf4]], <4 x float> poison, <4 x i32> zeroinitializer - ; CHECK: fmul <4 x float> %p0, %.splat - - %hlsl.normalize = call <4 x float> @llvm.dx.normalize.v4f32(<4 x float> %p0) - ret <4 x float> %hlsl.normalize -} diff --git a/llvm/test/CodeGen/DirectX/normalize_error.ll b/llvm/test/CodeGen/DirectX/normalize_error.ll deleted file mode 100644 index 3041d2ecdd923..0000000000000 --- a/llvm/test/CodeGen/DirectX/normalize_error.ll +++ /dev/null @@ -1,10 +0,0 @@ -; RUN: not opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s - -; DXIL operation normalize does not support double overload type -; CHECK: Cannot create Dot2 operation: Invalid overload type - -define noundef <2 x double> @test_normalize_double2(<2 x double> noundef %p0) { -entry: - %hlsl.normalize = call <2 x double> @llvm.dx.normalize.v2f32(<2 x double> %p0) - ret <2 x double> %hlsl.normalize -} diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/normalize.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/normalize.ll index 057f0c716ddca..d23aa69297c90 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/normalize.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/normalize.ll @@ -9,6 +9,24 @@ ; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4 ; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4 +define noundef half @normalize_half(half noundef %a) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#float_16]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_16]] + ; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] Normalize %[[#arg0]] + %hlsl.normalize = call half @llvm.spv.normalize.f16(half %a) + ret half %hlsl.normalize +} + +define noundef float @normalize_float(float noundef %a) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#float_32]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_32]] + ; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] Normalize %[[#arg0]] + %hlsl.normalize = call float @llvm.spv.normalize.f32(float %a) + ret float %hlsl.normalize +} + define noundef <4 x half> @normalize_half4(<4 x half> noundef %a) { entry: ; CHECK: %[[#]] = OpFunction %[[#vec4_float_16]] None %[[#]] @@ -27,5 +45,7 @@ entry: ret <4 x float> %hlsl.normalize } +declare half @llvm.spv.normalize.f16(half) +declare float @llvm.spv.normalize.f32(float) declare <4 x half> @llvm.spv.normalize.v4f16(<4 x half>) declare <4 x float> @llvm.spv.normalize.v4f32(<4 x float>) diff --git a/llvm/test/CodeGen/SPIRV/opencl/normalize.ll b/llvm/test/CodeGen/SPIRV/opencl/normalize.ll new file mode 100644 index 0000000000000..82055c38347d8 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/opencl/normalize.ll @@ -0,0 +1,52 @@ +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: %[[#op_ext_cl:]] = OpExtInstImport "OpenCL.std" + +; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16 +; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4 +; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32 +; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4 + +define noundef half @normalize_half(half noundef %a) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#float_16]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_16]] + ; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_cl]] normalize %[[#arg0]] + %spv.normalize = call half @llvm.spv.normalize.f16(half %a) + ret half %spv.normalize +} + +define noundef float @normalize_float(float noundef %a) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#float_32]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_32]] + ; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_cl]] normalize %[[#arg0]] + %spv.normalize = call float @llvm.spv.normalize.f32(float %a) + ret float %spv.normalize +} + +define noundef <4 x half> @normalize_half4(<4 x half> noundef %a) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#vec4_float_16]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]] + ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_cl]] normalize %[[#arg0]] + %spv.normalize = call <4 x half> @llvm.spv.normalize.v4f16(<4 x half> %a) + ret <4 x half> %spv.normalize +} + +define noundef <4 x float> @normalize_float4(<4 x float> noundef %a) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#vec4_float_32]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]] + ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_cl]] normalize %[[#arg0]] + %spv.normalize = call <4 x float> @llvm.spv.normalize.v4f32(<4 x float> %a) + ret <4 x float> %spv.normalize +} + +declare half @llvm.spv.normalize.f16(half) +declare float @llvm.spv.normalize.f32(float) +declare <4 x half> @llvm.spv.normalize.v4f16(<4 x half>) +declare <4 x float> @llvm.spv.normalize.v4f32(<4 x float>) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
