[clang] [llvm] [HLSL] Move `normalize` implementation to header files (PR #216228)
Kaitlin Peng via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 13 18:57:07 PDT 2026
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 <kaitlinpeng at microsoft.com>
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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at -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 at -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 at -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 at -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 at -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 at -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 at -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 at -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 at -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>)
More information about the llvm-commits
mailing list