[clang] [llvm] Add length builtins and length HLSL function to DirectX Backend (PR #101256)
Joshua Batista via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 2 16:49:05 PDT 2024
https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/101256
>From 7027cf254ae1b6acfdfbbf5dbeda3c4d6a4b3c43 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 26 Jul 2024 15:41:01 -0700
Subject: [PATCH 01/13] first attempt
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 1 +
clang/include/clang/Basic/Builtins.td | 6 ++++++
clang/lib/CodeGen/CGBuiltin.cpp | 3 +++
clang/lib/Sema/SemaChecking.cpp | 1 +
clang/test/CodeGenHLSL/builtins/length.hlsl | 1 +
clang/test/SemaHLSL/BuiltIns/length-errors.hlsl | 1 +
7 files changed, 14 insertions(+)
create mode 100644 clang/test/CodeGenHLSL/builtins/length.hlsl
create mode 100644 clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index a747464582e77..45f081081a371 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -664,6 +664,7 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in
T __builtin_elementwise_cosh(T x) return the hyperbolic cosine of angle x in radians floating point types
T __builtin_elementwise_tanh(T x) return the hyperbolic tangent of angle x in radians floating point types
T __builtin_elementwise_floor(T x) return the largest integral value less than or equal to x floating point types
+ T __builtin_elementwise_length(T x) return the length of the specified floating-point vector floating point types
T __builtin_elementwise_log(T x) return the natural logarithm of x floating point types
T __builtin_elementwise_log2(T x) return the base 2 logarithm of x floating point types
T __builtin_elementwise_log10(T x) return the base 10 logarithm of x floating point types
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index dad44f45a847f..46f40889b4b33 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -243,6 +243,7 @@ DWARF Support in Clang
Floating Point Support in Clang
-------------------------------
+- Add ``__builtin_elementwise_length``builtin for floating point types only.
Fixed Point Support in Clang
----------------------------
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 4133f6ff40cf3..d6122a484c094 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1248,6 +1248,12 @@ def ElementwiseBitreverse : Builtin {
let Prototype = "void(...)";
}
+def ElementwiseLength : Builtin, F16F128MathTemplate {
+ let Spellings = ["__builtin_elementwise_length"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
+ let Prototype = "T(float, T)";
+}
+
def ElementwiseMax : Builtin {
let Spellings = ["__builtin_elementwise_max"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index f0651c280ff95..38c7cc8ab5a78 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3815,6 +3815,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_elementwise_exp2:
return RValue::get(emitBuiltinWithOneOverloadedType<1>(
*this, E, llvm::Intrinsic::exp2, "elt.exp2"));
+ case Builtin::BI__builtin_elementwise_length:
+ return RValue::get(emitBuiltinWithOneOverloadedType<1>(
+ *this, E, llvm::Intrinsic::length, "elt.length"));
case Builtin::BI__builtin_elementwise_log:
return RValue::get(emitBuiltinWithOneOverloadedType<1>(
*this, E, llvm::Intrinsic::log, "elt.log"));
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index bb30b1e289a1c..09e3b17571528 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2684,6 +2684,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__builtin_elementwise_exp:
case Builtin::BI__builtin_elementwise_exp2:
case Builtin::BI__builtin_elementwise_floor:
+ case Builtin::BI__builtin_elementwise_length:
case Builtin::BI__builtin_elementwise_log:
case Builtin::BI__builtin_elementwise_log2:
case Builtin::BI__builtin_elementwise_log10:
diff --git a/clang/test/CodeGenHLSL/builtins/length.hlsl b/clang/test/CodeGenHLSL/builtins/length.hlsl
new file mode 100644
index 0000000000000..2f259b79aa7e2
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/length.hlsl
@@ -0,0 +1 @@
+s
\ No newline at end of file
diff --git a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
new file mode 100644
index 0000000000000..2f259b79aa7e2
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
@@ -0,0 +1 @@
+s
\ No newline at end of file
>From fc20777ddb0d2e083fa92f3c1673e87874f8f935 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Tue, 30 Jul 2024 15:05:57 -0700
Subject: [PATCH 02/13] sema and codegen hlsl passes
---
clang/include/clang/Basic/Builtins.td | 12 +--
clang/lib/CodeGen/CGBuiltin.cpp | 19 ++++-
clang/lib/CodeGen/CGHLSLRuntime.h | 1 +
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 33 +++++++++
clang/lib/Sema/SemaChecking.cpp | 1 -
clang/lib/Sema/SemaHLSL.cpp | 22 ++++++
clang/test/CodeGenHLSL/builtins/length.hlsl | 74 ++++++++++++++++++-
.../test/SemaHLSL/BuiltIns/length-errors.hlsl | 32 +++++++-
llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 +
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 +
.../Target/DirectX/DXILIntrinsicExpansion.cpp | 39 ++++++++++
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 +-
12 files changed, 226 insertions(+), 13 deletions(-)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index d6122a484c094..0baadf0d196b2 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1248,12 +1248,6 @@ def ElementwiseBitreverse : Builtin {
let Prototype = "void(...)";
}
-def ElementwiseLength : Builtin, F16F128MathTemplate {
- let Spellings = ["__builtin_elementwise_length"];
- let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
- let Prototype = "T(float, T)";
-}
-
def ElementwiseMax : Builtin {
let Spellings = ["__builtin_elementwise_max"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
@@ -4713,6 +4707,12 @@ def HLSLIsinf : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
+def HLSLLength : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_length"];
+ let Attributes = [NoThrow, Const];
+ let Prototype = "void(...)";
+}
+
def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_lerp"];
let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 38c7cc8ab5a78..a28073ca9ccc5 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3815,9 +3815,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_elementwise_exp2:
return RValue::get(emitBuiltinWithOneOverloadedType<1>(
*this, E, llvm::Intrinsic::exp2, "elt.exp2"));
- case Builtin::BI__builtin_elementwise_length:
- return RValue::get(emitBuiltinWithOneOverloadedType<1>(
- *this, E, llvm::Intrinsic::length, "elt.length"));
case Builtin::BI__builtin_elementwise_log:
return RValue::get(emitBuiltinWithOneOverloadedType<1>(
*this, E, llvm::Intrinsic::log, "elt.log"));
@@ -18463,6 +18460,22 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
/*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getLerpIntrinsic(),
ArrayRef<Value *>{X, Y, S}, nullptr, "hlsl.lerp");
}
+ case Builtin::BI__builtin_hlsl_elementwise_length: {
+ Value *X = EmitScalarExpr(E->getArg(0));
+
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("length operand must have a float representation");
+ // if the operand is a scalar, we can use the fabs llvm intrinsic directly
+ if (!E->getArg(0)->getType()->isVectorType()) {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType);
+ return Builder.CreateCall(F, X);
+ }
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/X->getType()->getScalarType(),
+ CGM.getHLSLRuntime().getLengthIntrinsic(),
+ ArrayRef<Value *>{X}, nullptr, "hlsl.length");
+ }
case Builtin::BI__builtin_hlsl_elementwise_frac: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 8c067f4963955..3f2dc0ae7b84d 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -75,6 +75,7 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)
GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(Length, length)
GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt)
GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 09f26a4588c14..21ac25bba1acb 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -908,6 +908,39 @@ float3 lerp(float3, float3, float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_lerp)
float4 lerp(float4, float4, float4);
+
+//===----------------------------------------------------------------------===//
+// length builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T length(T x)
+/// \brief Returns the length of the specified floating-point vector.
+/// \param x [in] The vector of floats, or a scalar float.
+///
+/// Length is based on the following formula: sqrt(x[0]^2 + x[1]^2 + �).
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+half length(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+half length(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+half length(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+half length(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+float length(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+float length(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+float length(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+float length(float4);
+
//===----------------------------------------------------------------------===//
// log builtins
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 09e3b17571528..bb30b1e289a1c 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2684,7 +2684,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__builtin_elementwise_exp:
case Builtin::BI__builtin_elementwise_exp2:
case Builtin::BI__builtin_elementwise_floor:
- case Builtin::BI__builtin_elementwise_length:
case Builtin::BI__builtin_elementwise_log:
case Builtin::BI__builtin_elementwise_log2:
case Builtin::BI__builtin_elementwise_log10:
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 9940bc5b4a606..624cbd3777bb8 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1076,6 +1076,28 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return true;
break;
}
+ case Builtin::BI__builtin_hlsl_elementwise_length: {
+ if (SemaRef.checkArgCount(TheCall, 1))
+ return true;
+ if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
+ return true;
+
+ ExprResult A = TheCall->getArg(0);
+ QualType ArgTyA = A.get()->getType();
+ QualType RetTy;
+
+ if (auto *VTy = ArgTyA->getAs<VectorType>())
+ RetTy = VTy->getElementType();
+ else
+ RetTy = TheCall->getArg(0)->getType();
+
+ TheCall->setType(RetTy);
+
+
+ if (CheckFloatOrHalfRepresentations(&SemaRef, TheCall))
+ return true;
+ break;
+ }
case Builtin::BI__builtin_hlsl_mad: {
if (SemaRef.checkArgCount(TheCall, 3))
return true;
diff --git a/clang/test/CodeGenHLSL/builtins/length.hlsl b/clang/test/CodeGenHLSL/builtins/length.hlsl
index 2f259b79aa7e2..0af669f36e6ba 100644
--- a/clang/test/CodeGenHLSL/builtins/length.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/length.hlsl
@@ -1 +1,73 @@
-s
\ No newline at end of file
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
+// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN: --check-prefixes=CHECK,NATIVE_HALF
+// 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
+
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.fabs.f16(half
+// NO_HALF: call float @llvm.fabs.f32(float
+// NATIVE_HALF: ret half
+// NO_HALF: ret float
+half test_length_half(half p0)
+{
+ return length(p0);
+}
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v2f16
+// NO_HALF: %hlsl.length = call float @llvm.dx.length.v2f32(
+// NATIVE_HALF: ret half %hlsl.length
+// NO_HALF: ret float %hlsl.length
+half test_length_half2(half2 p0)
+{
+ return length(p0);
+}
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v3f16
+// NO_HALF: %hlsl.length = call float @llvm.dx.length.v3f32(
+// NATIVE_HALF: ret half %hlsl.length
+// NO_HALF: ret float %hlsl.length
+half test_length_half3(half3 p0)
+{
+ return length(p0);
+}
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v4f16
+// NO_HALF: %hlsl.length = call float @llvm.dx.length.v4f32(
+// NATIVE_HALF: ret half %hlsl.length
+// NO_HALF: ret float %hlsl.length
+half test_length_half4(half4 p0)
+{
+ return length(p0);
+}
+
+// CHECK: define noundef float @
+// CHECK: call float @llvm.fabs.f32(float
+// CHECK: ret float
+float test_length_float(float p0)
+{
+ return length(p0);
+}
+// CHECK: define noundef float @
+// CHECK: %hlsl.length = call float @llvm.dx.length.v2f32(
+// CHECK: ret float %hlsl.length
+float test_length_float2(float2 p0)
+{
+ return length(p0);
+}
+// CHECK: define noundef float @
+// CHECK: %hlsl.length = call float @llvm.dx.length.v3f32(
+// CHECK: ret float %hlsl.length
+float test_length_float3(float3 p0)
+{
+ return length(p0);
+}
+// CHECK: define noundef float @
+// CHECK: %hlsl.length = call float @llvm.dx.length.v4f32(
+// CHECK: ret float %hlsl.length
+float test_length_float4(float4 p0)
+{
+ return length(p0);
+}
\ No newline at end of file
diff --git a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
index 2f259b79aa7e2..781c344f0da17 100644
--- a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
@@ -1 +1,31 @@
-s
\ No newline at end of file
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected
+
+bool test_too_few_arg()
+{
+ return __builtin_hlsl_elementwise_length();
+ // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+bool2 test_too_many_arg(float2 p0)
+{
+ return __builtin_hlsl_elementwise_length(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_elementwise_length(p1);
+ // expected-error at -1 {passing 'bool' to parameter of incompatible type 'float'}}
+}
+
+bool builtin_length_int_to_float_promotion(int p1)
+{
+ return __builtin_hlsl_elementwise_length(p1);
+ // expected-error at -1 {{passing 'int' to parameter of incompatible type 'float'}}
+}
+
+bool2 builtin_length_int2_to_float2_promotion(int2 p1)
+{
+ return __builtin_hlsl_elementwise_length(p1);
+ // expected-error at -1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
+}
\ No newline at end of file
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index a7f212da2f5b6..47c01f899a926 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -55,6 +55,8 @@ def int_dx_isinf :
def int_dx_lerp : Intrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem, IntrWillReturn] >;
+def int_dx_length : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_anyfloat_ty]>;
+
def int_dx_imad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>;
def int_dx_umad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>;
def int_dx_rcp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index ef6ddf12c32f6..c91fe859d7cc2 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -63,5 +63,7 @@ let TargetPrefix = "spv" in {
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]>;
def int_spv_lerp : Intrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem, IntrWillReturn] >;
+ def int_spv_length : Intrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
+ [IntrNoMem, IntrWillReturn] >;
def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]>;
}
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index 4b162a35365c8..7ef5b9eae9310 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -42,6 +42,7 @@ static bool isIntrinsicExpansion(Function &F) {
case Intrinsic::dx_clamp:
case Intrinsic::dx_uclamp:
case Intrinsic::dx_lerp:
+ case Intrinsic::dx_length:
case Intrinsic::dx_sdot:
case Intrinsic::dx_udot:
return true;
@@ -157,6 +158,42 @@ static bool expandAnyIntrinsic(CallInst *Orig) {
return true;
}
+static bool expandLengthIntrinsic(CallInst *Orig) {
+ Value *X = Orig->getOperand(0);
+ IRBuilder<> Builder(Orig->getParent());
+ Builder.SetInsertPoint(Orig);
+ Type *Ty = X->getType();
+ Type *EltTy = Ty->getScalarType();
+
+ // Though dx.length does work on scalar type, we can optimize it to just emit
+ // fabs, in CGBuiltin.cpp. We shouldn't see a scalar type here because
+ // CGBuiltin.cpp should have emitted a fabs call.
+ assert(Ty->isVectorTy() && "dx.length only works on vector type");
+ Value *Elt = Builder.CreateExtractElement(X, (uint64_t)0);
+ auto *XVec = dyn_cast<FixedVectorType>(Ty);
+ unsigned size = XVec->getNumElements();
+ if (size > 1) {
+ Value *Sum = Builder.CreateFMul(Elt, Elt);
+ for (unsigned i = 1; i < size; i++) {
+ Elt = Builder.CreateExtractElement(X, i);
+ Value *Mul = Builder.CreateFMul(Elt, Elt);
+ Sum = Builder.CreateFAdd(Sum, Mul);
+ }
+ Value *Result = Builder.CreateIntrinsic(
+ EltTy, Intrinsic::sqrt, ArrayRef<Value *>{Sum}, nullptr, "elt.sqrt");
+
+ Orig->replaceAllUsesWith(Result);
+ Orig->eraseFromParent();
+ return true;
+ } else {
+ Value *Result = Builder.CreateIntrinsic(
+ EltTy, Intrinsic::fabs, ArrayRef<Value *>{Elt}, nullptr, "elt.abs");
+ Orig->replaceAllUsesWith(Result);
+ Orig->eraseFromParent();
+ return true;
+ }
+}
+
static bool expandLerpIntrinsic(CallInst *Orig) {
Value *X = Orig->getOperand(0);
Value *Y = Orig->getOperand(1);
@@ -280,6 +317,8 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) {
return expandClampIntrinsic(Orig, F.getIntrinsicID());
case Intrinsic::dx_lerp:
return expandLerpIntrinsic(Orig);
+ case Intrinsic::dx_length:
+ return expandLengthIntrinsic(Orig);
case Intrinsic::dx_sdot:
case Intrinsic::dx_udot:
return expandIntegerDot(Orig, F.getIntrinsicID());
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 8391e0dec9a39..0f0b7fee96559 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -280,7 +280,7 @@ void SPIRVInstructionSelector::setupMF(MachineFunction &MF, GISelKnownBits *KB,
CodeGenCoverage *CoverageInfo,
ProfileSummaryInfo *PSI,
BlockFrequencyInfo *BFI) {
- MMI = &MF.getMMI().getObjFileInfo<SPIRVMachineModuleInfo>();
+ // MMI = &MF.getMMI().getObjFileInfo<SPIRVMachineModuleInfo>();
MRI = &MF.getRegInfo();
GR.setCurrentFunc(MF);
InstructionSelector::setupMF(MF, KB, CoverageInfo, PSI, BFI);
>From 2fa4ffdc63e699e2b0e3c44e5dfb95284dbc5f6b Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Tue, 30 Jul 2024 15:25:47 -0700
Subject: [PATCH 03/13] clangformat
---
clang/lib/CodeGen/CGBuiltin.cpp | 6 +++---
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 1 -
clang/lib/Sema/SemaHLSL.cpp | 9 ++++-----
clang/test/CodeGenHLSL/builtins/length.hlsl | 2 +-
.../test/SemaHLSL/BuiltIns/length-errors.hlsl | 2 +-
llvm/include/llvm/IR/IntrinsicsDirectX.td | 1 -
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 --
.../Target/DirectX/DXILIntrinsicExpansion.cpp | 18 +++++++++---------
8 files changed, 18 insertions(+), 23 deletions(-)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index a28073ca9ccc5..9b0ab3d361f1b 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18462,7 +18462,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
}
case Builtin::BI__builtin_hlsl_elementwise_length: {
Value *X = EmitScalarExpr(E->getArg(0));
-
+
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
llvm_unreachable("length operand must have a float representation");
// if the operand is a scalar, we can use the fabs llvm intrinsic directly
@@ -18473,8 +18473,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
}
return Builder.CreateIntrinsic(
/*ReturnType=*/X->getType()->getScalarType(),
- CGM.getHLSLRuntime().getLengthIntrinsic(),
- ArrayRef<Value *>{X}, nullptr, "hlsl.length");
+ CGM.getHLSLRuntime().getLengthIntrinsic(), ArrayRef<Value *>{X},
+ nullptr, "hlsl.length");
}
case Builtin::BI__builtin_hlsl_elementwise_frac: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 21ac25bba1acb..03e74ef35b5bf 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -908,7 +908,6 @@ float3 lerp(float3, float3, float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_lerp)
float4 lerp(float4, float4, float4);
-
//===----------------------------------------------------------------------===//
// length builtins
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 75be844227672..183ff40c04642 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1083,19 +1083,18 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaRef.checkArgCount(TheCall, 1))
return true;
if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
- return true;
+ return true;
ExprResult A = TheCall->getArg(0);
QualType ArgTyA = A.get()->getType();
QualType RetTy;
- if (auto *VTy = ArgTyA->getAs<VectorType>())
+ if (auto *VTy = ArgTyA->getAs<VectorType>())
RetTy = VTy->getElementType();
- else
+ else
RetTy = TheCall->getArg(0)->getType();
- TheCall->setType(RetTy);
-
+ TheCall->setType(RetTy);
if (CheckFloatOrHalfRepresentations(&SemaRef, TheCall))
return true;
diff --git a/clang/test/CodeGenHLSL/builtins/length.hlsl b/clang/test/CodeGenHLSL/builtins/length.hlsl
index 0af669f36e6ba..ff9238d2d82e3 100644
--- a/clang/test/CodeGenHLSL/builtins/length.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/length.hlsl
@@ -70,4 +70,4 @@ float test_length_float3(float3 p0)
float test_length_float4(float4 p0)
{
return length(p0);
-}
\ No newline at end of file
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
index 781c344f0da17..85c317a1ee0ec 100644
--- a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
@@ -28,4 +28,4 @@ bool2 builtin_length_int2_to_float2_promotion(int2 p1)
{
return __builtin_hlsl_elementwise_length(p1);
// expected-error at -1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
-}
\ No newline at end of file
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 47c01f899a926..312c3862f240d 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -56,7 +56,6 @@ def int_dx_lerp : Intrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType
[IntrNoMem, IntrWillReturn] >;
def int_dx_length : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_anyfloat_ty]>;
-
def int_dx_imad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>;
def int_dx_umad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>;
def int_dx_rcp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index c91fe859d7cc2..ef6ddf12c32f6 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -63,7 +63,5 @@ let TargetPrefix = "spv" in {
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]>;
def int_spv_lerp : Intrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem, IntrWillReturn] >;
- def int_spv_length : Intrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
- [IntrNoMem, IntrWillReturn] >;
def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]>;
}
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index 7ef5b9eae9310..8c3dd54b9af18 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -181,17 +181,17 @@ static bool expandLengthIntrinsic(CallInst *Orig) {
}
Value *Result = Builder.CreateIntrinsic(
EltTy, Intrinsic::sqrt, ArrayRef<Value *>{Sum}, nullptr, "elt.sqrt");
-
- Orig->replaceAllUsesWith(Result);
+
+ Orig->replaceAllUsesWith(Result);
Orig->eraseFromParent();
- return true;
+ return true;
} else {
- Value *Result = Builder.CreateIntrinsic(
- EltTy, Intrinsic::fabs, ArrayRef<Value *>{Elt}, nullptr, "elt.abs");
- Orig->replaceAllUsesWith(Result);
- Orig->eraseFromParent();
- return true;
- }
+ Value *Result = Builder.CreateIntrinsic(
+ EltTy, Intrinsic::fabs, ArrayRef<Value *>{Elt}, nullptr, "elt.abs");
+ Orig->replaceAllUsesWith(Result);
+ Orig->eraseFromParent();
+ return true;
+ }
}
static bool expandLerpIntrinsic(CallInst *Orig) {
>From fa0601208ccbbdc586db1741b0143f8e9fa88bdd Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Tue, 30 Jul 2024 17:03:40 -0700
Subject: [PATCH 04/13] add length.ll, address all of Farzon's feedback
---
clang/docs/LanguageExtensions.rst | 1 -
clang/docs/ReleaseNotes.rst | 1 -
clang/lib/CodeGen/CGBuiltin.cpp | 8 +-
clang/lib/Sema/SemaHLSL.cpp | 5 +-
.../test/SemaHLSL/BuiltIns/length-errors.hlsl | 4 +-
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 +
.../Target/DirectX/DXILIntrinsicExpansion.cpp | 31 ++---
llvm/test/CodeGen/DirectX/length.ll | 107 ++++++++++++++++++
8 files changed, 127 insertions(+), 31 deletions(-)
create mode 100644 llvm/test/CodeGen/DirectX/length.ll
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 45f081081a371..a747464582e77 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -664,7 +664,6 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in
T __builtin_elementwise_cosh(T x) return the hyperbolic cosine of angle x in radians floating point types
T __builtin_elementwise_tanh(T x) return the hyperbolic tangent of angle x in radians floating point types
T __builtin_elementwise_floor(T x) return the largest integral value less than or equal to x floating point types
- T __builtin_elementwise_length(T x) return the length of the specified floating-point vector floating point types
T __builtin_elementwise_log(T x) return the natural logarithm of x floating point types
T __builtin_elementwise_log2(T x) return the base 2 logarithm of x floating point types
T __builtin_elementwise_log10(T x) return the base 10 logarithm of x floating point types
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 34dbb26a66b82..3c2e0282d1c72 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -249,7 +249,6 @@ DWARF Support in Clang
Floating Point Support in Clang
-------------------------------
-- Add ``__builtin_elementwise_length``builtin for floating point types only.
Fixed Point Support in Clang
----------------------------
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 9b0ab3d361f1b..1b67eaf9ab3ca 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18466,11 +18466,9 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
llvm_unreachable("length operand must have a float representation");
// if the operand is a scalar, we can use the fabs llvm intrinsic directly
- if (!E->getArg(0)->getType()->isVectorType()) {
- llvm::Type *ResultType = ConvertType(E->getType());
- Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType);
- return Builder.CreateCall(F, X);
- }
+ if (!E->getArg(0)->getType()->isVectorType())
+ return EmitFAbs(*this, X);
+
return Builder.CreateIntrinsic(
/*ReturnType=*/X->getType()->getScalarType(),
CGM.getHLSLRuntime().getLengthIntrinsic(), ArrayRef<Value *>{X},
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 183ff40c04642..ee307a7da2136 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1080,6 +1080,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
break;
}
case Builtin::BI__builtin_hlsl_elementwise_length: {
+ if (CheckFloatOrHalfRepresentations(&SemaRef, TheCall))
+ return true;
if (SemaRef.checkArgCount(TheCall, 1))
return true;
if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
@@ -1095,9 +1097,6 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
RetTy = TheCall->getArg(0)->getType();
TheCall->setType(RetTy);
-
- if (CheckFloatOrHalfRepresentations(&SemaRef, TheCall))
- return true;
break;
}
case Builtin::BI__builtin_hlsl_mad: {
diff --git a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
index 85c317a1ee0ec..b1153a7782d35 100644
--- a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
@@ -1,12 +1,12 @@
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected
-bool test_too_few_arg()
+void test_too_few_arg()
{
return __builtin_hlsl_elementwise_length();
// expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
}
-bool2 test_too_many_arg(float2 p0)
+void test_too_many_arg(float2 p0)
{
return __builtin_hlsl_elementwise_length(p0, p0);
// expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index ef6ddf12c32f6..3f77ef6bfcdbe 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -63,5 +63,6 @@ let TargetPrefix = "spv" in {
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]>;
def int_spv_lerp : Intrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem, IntrWillReturn] >;
+ def int_spv_length : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_anyfloat_ty]>;
def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]>;
}
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index 8c3dd54b9af18..f7a1c91a10803 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -168,30 +168,23 @@ static bool expandLengthIntrinsic(CallInst *Orig) {
// Though dx.length does work on scalar type, we can optimize it to just emit
// fabs, in CGBuiltin.cpp. We shouldn't see a scalar type here because
// CGBuiltin.cpp should have emitted a fabs call.
- assert(Ty->isVectorTy() && "dx.length only works on vector type");
Value *Elt = Builder.CreateExtractElement(X, (uint64_t)0);
auto *XVec = dyn_cast<FixedVectorType>(Ty);
unsigned size = XVec->getNumElements();
- if (size > 1) {
- Value *Sum = Builder.CreateFMul(Elt, Elt);
- for (unsigned i = 1; i < size; i++) {
- Elt = Builder.CreateExtractElement(X, i);
- Value *Mul = Builder.CreateFMul(Elt, Elt);
- Sum = Builder.CreateFAdd(Sum, Mul);
- }
- Value *Result = Builder.CreateIntrinsic(
- EltTy, Intrinsic::sqrt, ArrayRef<Value *>{Sum}, nullptr, "elt.sqrt");
+ assert(Ty->isVectorTy() && size > 1 && "dx.length only works on vector type");
- Orig->replaceAllUsesWith(Result);
- Orig->eraseFromParent();
- return true;
- } else {
- Value *Result = Builder.CreateIntrinsic(
- EltTy, Intrinsic::fabs, ArrayRef<Value *>{Elt}, nullptr, "elt.abs");
- Orig->replaceAllUsesWith(Result);
- Orig->eraseFromParent();
- return true;
+ Value *Sum = Builder.CreateFMul(Elt, Elt);
+ for (unsigned i = 1; i < size; i++) {
+ Elt = Builder.CreateExtractElement(X, i);
+ Value *Mul = Builder.CreateFMul(Elt, Elt);
+ Sum = Builder.CreateFAdd(Sum, Mul);
}
+ Value *Result = Builder.CreateIntrinsic(
+ EltTy, Intrinsic::sqrt, ArrayRef<Value *>{Sum}, nullptr, "elt.sqrt");
+
+ Orig->replaceAllUsesWith(Result);
+ Orig->eraseFromParent();
+ return true;
}
static bool expandLerpIntrinsic(CallInst *Orig) {
diff --git a/llvm/test/CodeGen/DirectX/length.ll b/llvm/test/CodeGen/DirectX/length.ll
new file mode 100644
index 0000000000000..2047ba18c1bc9
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/length.ll
@@ -0,0 +1,107 @@
+; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
+; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
+
+; ModuleID = 'D:\llvm-project\clang\test\CodeGenHLSL\builtins\length.hlsl'
+source_filename = "D:\\llvm-project\\clang\\test\\CodeGenHLSL\\builtins\\length.hlsl"
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxilv1.3-pc-shadermodel6.3-library"
+
+; Function Attrs: convergent noinline nounwind optnone
+define noundef float @"?test_length_half@@YA$halff@$halff@@Z"(float noundef %p0) #0 {
+entry:
+ %p0.addr = alloca float, align 4
+ store float %p0, ptr %p0.addr, align 4
+ %0 = load float, ptr %p0.addr, align 4
+
+ ; EXPCHECK: call float @llvm.fabs.f32(float %{{.*}})
+ ; DOPCHECK: call float @dx.op.unary.f32(i32 6, float %{{.*}})
+ %1 = call float @llvm.fabs.f32(float %0) #3
+ ret float %1
+}
+
+; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
+declare float @llvm.fabs.f32(float) #1
+
+; Function Attrs: convergent noinline nounwind optnone
+define noundef float @"?test_length_half2@@YA$halff at T?$__vector@$halff@$01 at __clang@@@Z"(<2 x float> noundef %p0) #0 {
+entry:
+ %p0.addr = alloca <2 x float>, align 8
+ store <2 x float> %p0, ptr %p0.addr, align 8
+ %0 = load <2 x float>, ptr %p0.addr, align 8
+
+ ; CHECK: extractelement <2 x float> %{{.*}}, i64 0
+ ; CHECK: fmul float %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <2 x float> %{{.*}}, i64 1
+ ; CHECK: fmul float %{{.*}}, %{{.*}}
+ ; CHECK: fadd float %{{.*}}, %{{.*}}
+ ; EXPCHECK: call float @llvm.sqrt.f32(float %{{.*}})
+ ; DOPCHECK: call float @dx.op.unary.f32(i32 24, float %{{.*}})
+
+ %hlsl.length = call float @llvm.dx.length.v2f32(<2 x float> %0)
+ ret float %hlsl.length
+}
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn
+declare float @llvm.dx.length.v2f32(<2 x float>) #2
+
+; Function Attrs: convergent noinline nounwind optnone
+define noundef float @"?test_length_half3@@YA$halff at T?$__vector@$halff@$02 at __clang@@@Z"(<3 x float> noundef %p0) #0 {
+entry:
+ %p0.addr = alloca <3 x float>, align 16
+ store <3 x float> %p0, ptr %p0.addr, align 16
+ %0 = load <3 x float>, ptr %p0.addr, align 16
+
+ ; CHECK: extractelement <3 x float> %{{.*}}, i64 0
+ ; CHECK: fmul float %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <3 x float> %{{.*}}, i64 1
+ ; CHECK: fmul float %{{.*}}, %{{.*}}
+ ; CHECK: fadd float %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <3 x float> %{{.*}}, i64 2
+ ; CHECK: fmul float %{{.*}}, %{{.*}}
+ ; CHECK: fadd float %{{.*}}, %{{.*}}
+ ; EXPCHECK: call float @llvm.sqrt.f32(float %{{.*}})
+ ; DOPCHECK: call float @dx.op.unary.f32(i32 24, float %{{.*}})
+
+ %hlsl.length = call float @llvm.dx.length.v3f32(<3 x float> %0)
+ ret float %hlsl.length
+}
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn
+declare float @llvm.dx.length.v3f32(<3 x float>) #2
+
+; Function Attrs: convergent noinline nounwind optnone
+define noundef float @"?test_length_half4@@YA$halff at T?$__vector@$halff@$03 at __clang@@@Z"(<4 x float> noundef %p0) #0 {
+entry:
+ %p0.addr = alloca <4 x float>, align 16
+ store <4 x float> %p0, ptr %p0.addr, align 16
+ %0 = load <4 x float>, ptr %p0.addr, align 16
+
+ ; CHECK: extractelement <4 x float> %{{.*}}, i64 0
+ ; CHECK: fmul float %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <4 x float> %{{.*}}, i64 1
+ ; CHECK: fmul float %{{.*}}, %{{.*}}
+ ; CHECK: fadd float %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <4 x float> %{{.*}}, i64 2
+ ; CHECK: fmul float %{{.*}}, %{{.*}}
+ ; CHECK: fadd float %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <4 x float> %{{.*}}, i64 3
+ ; CHECK: fmul float %{{.*}}, %{{.*}}
+ ; CHECK: fadd float %{{.*}}, %{{.*}}
+ ; EXPCHECK: call float @llvm.sqrt.f32(float %{{.*}})
+ ; DOPCHECK: call float @dx.op.unary.f32(i32 24, float %{{.*}})
+
+ %hlsl.length = call float @llvm.dx.length.v4f32(<4 x float> %0)
+ ret float %hlsl.length
+}
+
+attributes #0 = { convergent noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+attributes #2 = { nocallback nofree nosync nounwind willreturn }
+attributes #3 = { memory(none) }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
+!2 = !{!"clang version 20.0.0git (git at github.com:bob80905/llvm-project.git 2fa4ffdc63e699e2b0e3c44e5dfb95284dbc5f6b)"}
\ No newline at end of file
>From 46dec9d70e306b13aa6385a484d95d46cf35913d Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 31 Jul 2024 11:26:01 -0700
Subject: [PATCH 05/13] address all of farzon's feedback, add length_error.ll
---
clang/test/CodeGenHLSL/builtins/length.hlsl | 16 +--
.../test/SemaHLSL/BuiltIns/length-errors.hlsl | 10 +-
llvm/test/CodeGen/DirectX/length.ll | 132 +++++++++++-------
llvm/test/CodeGen/DirectX/length_error.ll | 10 ++
4 files changed, 102 insertions(+), 66 deletions(-)
create mode 100644 llvm/test/CodeGen/DirectX/length_error.ll
diff --git a/clang/test/CodeGenHLSL/builtins/length.hlsl b/clang/test/CodeGenHLSL/builtins/length.hlsl
index ff9238d2d82e3..1c23b0df04df9 100644
--- a/clang/test/CodeGenHLSL/builtins/length.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/length.hlsl
@@ -13,7 +13,7 @@
// NO_HALF: ret float
half test_length_half(half p0)
{
- return length(p0);
+ return length(p0);
}
// NATIVE_HALF: define noundef half @
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v2f16
@@ -22,7 +22,7 @@ half test_length_half(half p0)
// NO_HALF: ret float %hlsl.length
half test_length_half2(half2 p0)
{
- return length(p0);
+ return length(p0);
}
// NATIVE_HALF: define noundef half @
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v3f16
@@ -31,7 +31,7 @@ half test_length_half2(half2 p0)
// NO_HALF: ret float %hlsl.length
half test_length_half3(half3 p0)
{
- return length(p0);
+ return length(p0);
}
// NATIVE_HALF: define noundef half @
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v4f16
@@ -40,7 +40,7 @@ half test_length_half3(half3 p0)
// NO_HALF: ret float %hlsl.length
half test_length_half4(half4 p0)
{
- return length(p0);
+ return length(p0);
}
// CHECK: define noundef float @
@@ -48,26 +48,26 @@ half test_length_half4(half4 p0)
// CHECK: ret float
float test_length_float(float p0)
{
- return length(p0);
+ return length(p0);
}
// CHECK: define noundef float @
// CHECK: %hlsl.length = call float @llvm.dx.length.v2f32(
// CHECK: ret float %hlsl.length
float test_length_float2(float2 p0)
{
- return length(p0);
+ return length(p0);
}
// CHECK: define noundef float @
// CHECK: %hlsl.length = call float @llvm.dx.length.v3f32(
// CHECK: ret float %hlsl.length
float test_length_float3(float3 p0)
{
- return length(p0);
+ return length(p0);
}
// CHECK: define noundef float @
// CHECK: %hlsl.length = call float @llvm.dx.length.v4f32(
// CHECK: ret float %hlsl.length
float test_length_float4(float4 p0)
{
- return length(p0);
+ return length(p0);
}
diff --git a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
index b1153a7782d35..0f7d8b2d65eaf 100644
--- a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
@@ -2,30 +2,30 @@
void test_too_few_arg()
{
- return __builtin_hlsl_elementwise_length();
+ return __builtin_hlsl_elementwise_length();
// expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
}
void test_too_many_arg(float2 p0)
{
- return __builtin_hlsl_elementwise_length(p0, p0);
+ return __builtin_hlsl_elementwise_length(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_elementwise_length(p1);
+ return __builtin_hlsl_elementwise_length(p1);
// expected-error at -1 {passing 'bool' to parameter of incompatible type 'float'}}
}
bool builtin_length_int_to_float_promotion(int p1)
{
- return __builtin_hlsl_elementwise_length(p1);
+ return __builtin_hlsl_elementwise_length(p1);
// expected-error at -1 {{passing 'int' to parameter of incompatible type 'float'}}
}
bool2 builtin_length_int2_to_float2_promotion(int2 p1)
{
- return __builtin_hlsl_elementwise_length(p1);
+ return __builtin_hlsl_elementwise_length(p1);
// expected-error at -1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
}
diff --git a/llvm/test/CodeGen/DirectX/length.ll b/llvm/test/CodeGen/DirectX/length.ll
index 2047ba18c1bc9..b5ca4b0dc5cbf 100644
--- a/llvm/test/CodeGen/DirectX/length.ll
+++ b/llvm/test/CodeGen/DirectX/length.ll
@@ -1,34 +1,88 @@
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
-; ModuleID = 'D:\llvm-project\clang\test\CodeGenHLSL\builtins\length.hlsl'
-source_filename = "D:\\llvm-project\\clang\\test\\CodeGenHLSL\\builtins\\length.hlsl"
-target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
target triple = "dxilv1.3-pc-shadermodel6.3-library"
-; Function Attrs: convergent noinline nounwind optnone
-define noundef float @"?test_length_half@@YA$halff@$halff@@Z"(float noundef %p0) #0 {
-entry:
- %p0.addr = alloca float, align 4
- store float %p0, ptr %p0.addr, align 4
- %0 = load float, ptr %p0.addr, align 4
+declare half @llvm.fabs.f16(half)
+declare half @llvm.dx.length.v2f16(<2 x half>)
+declare half @llvm.dx.length.v3f16(<3 x half>)
+declare half @llvm.dx.length.v4f16(<4 x half>)
+
+declare float @llvm.fabs.f32(float)
+declare float @llvm.dx.length.v2f32(<2 x float>)
+declare float @llvm.dx.length.v3f32(<3 x float>)
+declare float @llvm.dx.length.v4f32(<4 x float>)
+
+define noundef half @test_length_half(half noundef %p0) {
+entry:
+ ; EXPCHECK: call half @llvm.fabs.f16(half %{{.*}})
+ ; DOPCHECK: call half @dx.op.unary.f16(i32 6, half %{{.*}})
+ %0 = call half @llvm.fabs.f16(half %p0)
+ ret half %0
+}
- ; EXPCHECK: call float @llvm.fabs.f32(float %{{.*}})
- ; DOPCHECK: call float @dx.op.unary.f32(i32 6, float %{{.*}})
- %1 = call float @llvm.fabs.f32(float %0) #3
- ret float %1
+define noundef half @test_length_half2(<2 x half> noundef %p0) {
+entry:
+ ; CHECK: extractelement <2 x half> %{{.*}}, i64 0
+ ; CHECK: fmul half %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <2 x half> %{{.*}}, i64 1
+ ; CHECK: fmul half %{{.*}}, %{{.*}}
+ ; CHECK: fadd half %{{.*}}, %{{.*}}
+ ; EXPCHECK: call half @llvm.sqrt.f16(half %{{.*}})
+ ; DOPCHECK: call half @dx.op.unary.f16(i32 24, half %{{.*}})
+
+ %hlsl.length = call half @llvm.dx.length.v2f16(<2 x half> %p0)
+ ret half %hlsl.length
}
-; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
-declare float @llvm.fabs.f32(float) #1
+define noundef half @test_length_half3(<3 x half> noundef %p0) {
+entry:
+ ; CHECK: extractelement <3 x half> %{{.*}}, i64 0
+ ; CHECK: fmul half %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <3 x half> %{{.*}}, i64 1
+ ; CHECK: fmul half %{{.*}}, %{{.*}}
+ ; CHECK: fadd half %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <3 x half> %{{.*}}, i64 2
+ ; CHECK: fmul half %{{.*}}, %{{.*}}
+ ; CHECK: fadd half %{{.*}}, %{{.*}}
+ ; EXPCHECK: call half @llvm.sqrt.f16(half %{{.*}})
+ ; DOPCHECK: call half @dx.op.unary.f16(i32 24, half %{{.*}})
+
+ %hlsl.length = call half @llvm.dx.length.v3f16(<3 x half> %p0)
+ ret half %hlsl.length
+}
-; Function Attrs: convergent noinline nounwind optnone
-define noundef float @"?test_length_half2@@YA$halff at T?$__vector@$halff@$01 at __clang@@@Z"(<2 x float> noundef %p0) #0 {
+define noundef half @test_length_half4(<4 x half> noundef %p0) {
entry:
- %p0.addr = alloca <2 x float>, align 8
- store <2 x float> %p0, ptr %p0.addr, align 8
- %0 = load <2 x float>, ptr %p0.addr, align 8
+ ; CHECK: extractelement <4 x half> %{{.*}}, i64 0
+ ; CHECK: fmul half %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <4 x half> %{{.*}}, i64 1
+ ; CHECK: fmul half %{{.*}}, %{{.*}}
+ ; CHECK: fadd half %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <4 x half> %{{.*}}, i64 2
+ ; CHECK: fmul half %{{.*}}, %{{.*}}
+ ; CHECK: fadd half %{{.*}}, %{{.*}}
+ ; CHECK: extractelement <4 x half> %{{.*}}, i64 3
+ ; CHECK: fmul half %{{.*}}, %{{.*}}
+ ; CHECK: fadd half %{{.*}}, %{{.*}}
+ ; EXPCHECK: call half @llvm.sqrt.f16(half %{{.*}})
+ ; DOPCHECK: call half @dx.op.unary.f16(i32 24, half %{{.*}})
+
+ %hlsl.length = call half @llvm.dx.length.v4f16(<4 x half> %p0)
+ ret half %hlsl.length
+}
+define noundef float @test_length_float(float noundef %p0) {
+entry:
+ ; EXPCHECK: call float @llvm.fabs.f32(float %p0)
+ ; DOPCHECK: call float @dx.op.unary.f32(i32 6, float %{{.*}})
+
+ %0 = call float @llvm.fabs.f32(float %p0)
+ ret float %0
+}
+
+define noundef float @test_length_float2(<2 x float> noundef %p0) {
+entry:
; CHECK: extractelement <2 x float> %{{.*}}, i64 0
; CHECK: fmul float %{{.*}}, %{{.*}}
; CHECK: extractelement <2 x float> %{{.*}}, i64 1
@@ -37,20 +91,12 @@ entry:
; EXPCHECK: call float @llvm.sqrt.f32(float %{{.*}})
; DOPCHECK: call float @dx.op.unary.f32(i32 24, float %{{.*}})
- %hlsl.length = call float @llvm.dx.length.v2f32(<2 x float> %0)
+ %hlsl.length = call float @llvm.dx.length.v2f32(<2 x float> %p0)
ret float %hlsl.length
}
-; Function Attrs: nocallback nofree nosync nounwind willreturn
-declare float @llvm.dx.length.v2f32(<2 x float>) #2
-
-; Function Attrs: convergent noinline nounwind optnone
-define noundef float @"?test_length_half3@@YA$halff at T?$__vector@$halff@$02 at __clang@@@Z"(<3 x float> noundef %p0) #0 {
+define noundef float @test_length_float3(<3 x float> noundef %p0) {
entry:
- %p0.addr = alloca <3 x float>, align 16
- store <3 x float> %p0, ptr %p0.addr, align 16
- %0 = load <3 x float>, ptr %p0.addr, align 16
-
; CHECK: extractelement <3 x float> %{{.*}}, i64 0
; CHECK: fmul float %{{.*}}, %{{.*}}
; CHECK: extractelement <3 x float> %{{.*}}, i64 1
@@ -62,20 +108,12 @@ entry:
; EXPCHECK: call float @llvm.sqrt.f32(float %{{.*}})
; DOPCHECK: call float @dx.op.unary.f32(i32 24, float %{{.*}})
- %hlsl.length = call float @llvm.dx.length.v3f32(<3 x float> %0)
+ %hlsl.length = call float @llvm.dx.length.v3f32(<3 x float> %p0)
ret float %hlsl.length
}
-; Function Attrs: nocallback nofree nosync nounwind willreturn
-declare float @llvm.dx.length.v3f32(<3 x float>) #2
-
-; Function Attrs: convergent noinline nounwind optnone
-define noundef float @"?test_length_half4@@YA$halff at T?$__vector@$halff@$03 at __clang@@@Z"(<4 x float> noundef %p0) #0 {
+define noundef float @test_length_float4(<4 x float> noundef %p0) {
entry:
- %p0.addr = alloca <4 x float>, align 16
- store <4 x float> %p0, ptr %p0.addr, align 16
- %0 = load <4 x float>, ptr %p0.addr, align 16
-
; CHECK: extractelement <4 x float> %{{.*}}, i64 0
; CHECK: fmul float %{{.*}}, %{{.*}}
; CHECK: extractelement <4 x float> %{{.*}}, i64 1
@@ -90,18 +128,6 @@ entry:
; EXPCHECK: call float @llvm.sqrt.f32(float %{{.*}})
; DOPCHECK: call float @dx.op.unary.f32(i32 24, float %{{.*}})
- %hlsl.length = call float @llvm.dx.length.v4f32(<4 x float> %0)
+ %hlsl.length = call float @llvm.dx.length.v4f32(<4 x float> %p0)
ret float %hlsl.length
}
-
-attributes #0 = { convergent noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
-attributes #2 = { nocallback nofree nosync nounwind willreturn }
-attributes #3 = { memory(none) }
-
-!llvm.module.flags = !{!0, !1}
-!llvm.ident = !{!2}
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
-!2 = !{!"clang version 20.0.0git (git at github.com:bob80905/llvm-project.git 2fa4ffdc63e699e2b0e3c44e5dfb95284dbc5f6b)"}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/DirectX/length_error.ll b/llvm/test/CodeGen/DirectX/length_error.ll
new file mode 100644
index 0000000000000..9c747c36804a6
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/length_error.ll
@@ -0,0 +1,10 @@
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
+
+; DXIL operation length does not support double overload type
+; CHECK: LLVM ERROR: Invalid Overload
+
+define noundef double @test_length_double2(<2 x double> noundef %p0) {
+entry:
+ %hlsl.length = call double @llvm.dx.length.v2f32(<2 x double> %p0)
+ ret double %hlsl.length
+}
\ No newline at end of file
>From 0af5ca8847c7927fb66fc075e1c97606f1a35833 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 31 Jul 2024 11:27:57 -0700
Subject: [PATCH 06/13] remove target triple variable, define target triple in
flag on dxil-op-lower run line
---
llvm/test/CodeGen/DirectX/length.ll | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/llvm/test/CodeGen/DirectX/length.ll b/llvm/test/CodeGen/DirectX/length.ll
index b5ca4b0dc5cbf..c1133f973332d 100644
--- a/llvm/test/CodeGen/DirectX/length.ll
+++ b/llvm/test/CodeGen/DirectX/length.ll
@@ -1,7 +1,5 @@
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
-
-target triple = "dxilv1.3-pc-shadermodel6.3-library"
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
declare half @llvm.fabs.f16(half)
declare half @llvm.dx.length.v2f16(<2 x half>)
>From 8857963c5a537b0fc1e5003bac67bebf234c5d57 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 31 Jul 2024 11:31:23 -0700
Subject: [PATCH 07/13] add new line to length_error.ll
---
llvm/test/CodeGen/DirectX/length_error.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/DirectX/length_error.ll b/llvm/test/CodeGen/DirectX/length_error.ll
index 9c747c36804a6..952c9155b2599 100644
--- a/llvm/test/CodeGen/DirectX/length_error.ll
+++ b/llvm/test/CodeGen/DirectX/length_error.ll
@@ -7,4 +7,4 @@ define noundef double @test_length_double2(<2 x double> noundef %p0) {
entry:
%hlsl.length = call double @llvm.dx.length.v2f32(<2 x double> %p0)
ret double %hlsl.length
-}
\ No newline at end of file
+}
>From 9ac29685a8f3841b8260f509dd337e38921ea854 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 31 Jul 2024 11:53:11 -0700
Subject: [PATCH 08/13] add test description on length.ll
---
llvm/test/CodeGen/DirectX/length.ll | 2 ++
1 file changed, 2 insertions(+)
diff --git a/llvm/test/CodeGen/DirectX/length.ll b/llvm/test/CodeGen/DirectX/length.ll
index c1133f973332d..fc7384267912c 100644
--- a/llvm/test/CodeGen/DirectX/length.ll
+++ b/llvm/test/CodeGen/DirectX/length.ll
@@ -1,6 +1,8 @@
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
+; Make sure dxil operation function calls for length are generated for half/float.
+
declare half @llvm.fabs.f16(half)
declare half @llvm.dx.length.v2f16(<2 x half>)
declare half @llvm.dx.length.v3f16(<3 x half>)
>From 2f7f10d310744866043522a1efa9d6326ba416a3 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 1 Aug 2024 11:58:09 -0700
Subject: [PATCH 09/13] Update
llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
Co-authored-by: Justin Bogner <mail at justinbogner.com>
---
llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index f7a1c91a10803..97fd7c007c1b1 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -174,8 +174,8 @@ static bool expandLengthIntrinsic(CallInst *Orig) {
assert(Ty->isVectorTy() && size > 1 && "dx.length only works on vector type");
Value *Sum = Builder.CreateFMul(Elt, Elt);
- for (unsigned i = 1; i < size; i++) {
- Elt = Builder.CreateExtractElement(X, i);
+ for (unsigned I = 1; I < size; I++) {
+ Elt = Builder.CreateExtractElement(X, I);
Value *Mul = Builder.CreateFMul(Elt, Elt);
Sum = Builder.CreateFAdd(Sum, Mul);
}
>From b620bab4f3731d42b4e0b99674c971b9dbad1d83 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 1 Aug 2024 11:59:23 -0700
Subject: [PATCH 10/13] Update clang/lib/CodeGen/CGBuiltin.cpp
Co-authored-by: Justin Bogner <mail at justinbogner.com>
---
clang/lib/CodeGen/CGBuiltin.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 1b67eaf9ab3ca..e071b384bccb8 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18463,8 +18463,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
case Builtin::BI__builtin_hlsl_elementwise_length: {
Value *X = EmitScalarExpr(E->getArg(0));
- if (!E->getArg(0)->getType()->hasFloatingRepresentation())
- llvm_unreachable("length operand must have a float representation");
+ assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
+ "length operand must have a float representation");
// if the operand is a scalar, we can use the fabs llvm intrinsic directly
if (!E->getArg(0)->getType()->isVectorType())
return EmitFAbs(*this, X);
>From 3eab70e94d8073a54385153dd5ba0f16f802407b Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 1 Aug 2024 13:21:33 -0700
Subject: [PATCH 11/13] don't use elementwise, rename some vars
---
clang/include/clang/Basic/Builtins.td | 2 +-
clang/lib/CodeGen/CGBuiltin.cpp | 2 +-
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 16 ++++++++--------
clang/lib/Sema/SemaHLSL.cpp | 4 +---
clang/test/SemaHLSL/BuiltIns/length-errors.hlsl | 10 +++++-----
.../Target/DirectX/DXILIntrinsicExpansion.cpp | 7 ++++---
llvm/test/CodeGen/DirectX/length.ll | 17 -----------------
7 files changed, 20 insertions(+), 38 deletions(-)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 0baadf0d196b2..cc64469da9e4a 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4708,7 +4708,7 @@ def HLSLIsinf : LangBuiltin<"HLSL_LANG"> {
}
def HLSLLength : LangBuiltin<"HLSL_LANG"> {
- let Spellings = ["__builtin_hlsl_elementwise_length"];
+ let Spellings = ["__builtin_hlsl_length"];
let Attributes = [NoThrow, Const];
let Prototype = "void(...)";
}
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index e071b384bccb8..7406acbcca7c4 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18460,7 +18460,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
/*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getLerpIntrinsic(),
ArrayRef<Value *>{X, Y, S}, nullptr, "hlsl.lerp");
}
- case Builtin::BI__builtin_hlsl_elementwise_length: {
+ case Builtin::BI__builtin_hlsl_length: {
Value *X = EmitScalarExpr(E->getArg(0));
assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 03e74ef35b5bf..e1a2b5135c8a4 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -919,25 +919,25 @@ float4 lerp(float4, float4, float4);
/// Length is based on the following formula: sqrt(x[0]^2 + x[1]^2 + �).
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_length)
half length(half);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_length)
half length(half2);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_length)
half length(half3);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_length)
half length(half4);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_length)
float length(float);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_length)
float length(float2);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_length)
float length(float3);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_length)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_length)
float length(float4);
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index ee307a7da2136..203be090638e6 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1079,13 +1079,11 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return true;
break;
}
- case Builtin::BI__builtin_hlsl_elementwise_length: {
+ case Builtin::BI__builtin_hlsl_length: {
if (CheckFloatOrHalfRepresentations(&SemaRef, TheCall))
return true;
if (SemaRef.checkArgCount(TheCall, 1))
return true;
- if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
- return true;
ExprResult A = TheCall->getArg(0);
QualType ArgTyA = A.get()->getType();
diff --git a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
index 0f7d8b2d65eaf..fe0046a2ab5a1 100644
--- a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl
@@ -2,30 +2,30 @@
void test_too_few_arg()
{
- return __builtin_hlsl_elementwise_length();
+ return __builtin_hlsl_length();
// expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
}
void test_too_many_arg(float2 p0)
{
- return __builtin_hlsl_elementwise_length(p0, p0);
+ return __builtin_hlsl_length(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_elementwise_length(p1);
+ return __builtin_hlsl_length(p1);
// expected-error at -1 {passing 'bool' to parameter of incompatible type 'float'}}
}
bool builtin_length_int_to_float_promotion(int p1)
{
- return __builtin_hlsl_elementwise_length(p1);
+ return __builtin_hlsl_length(p1);
// expected-error at -1 {{passing 'int' to parameter of incompatible type 'float'}}
}
bool2 builtin_length_int2_to_float2_promotion(int2 p1)
{
- return __builtin_hlsl_elementwise_length(p1);
+ return __builtin_hlsl_length(p1);
// expected-error at -1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
}
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index 97fd7c007c1b1..501231298ed25 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -170,11 +170,12 @@ static bool expandLengthIntrinsic(CallInst *Orig) {
// CGBuiltin.cpp should have emitted a fabs call.
Value *Elt = Builder.CreateExtractElement(X, (uint64_t)0);
auto *XVec = dyn_cast<FixedVectorType>(Ty);
- unsigned size = XVec->getNumElements();
- assert(Ty->isVectorTy() && size > 1 && "dx.length only works on vector type");
+ unsigned XVecSize = XVec->getNumElements();
+ assert(Ty->isVectorTy() && XVecSize > 1 &&
+ "dx.length requires a vector of length 2 or more");
Value *Sum = Builder.CreateFMul(Elt, Elt);
- for (unsigned I = 1; I < size; I++) {
+ for (unsigned I = 1; I < XVecSize; I++) {
Elt = Builder.CreateExtractElement(X, I);
Value *Mul = Builder.CreateFMul(Elt, Elt);
Sum = Builder.CreateFAdd(Sum, Mul);
diff --git a/llvm/test/CodeGen/DirectX/length.ll b/llvm/test/CodeGen/DirectX/length.ll
index fc7384267912c..d12fcf4722a07 100644
--- a/llvm/test/CodeGen/DirectX/length.ll
+++ b/llvm/test/CodeGen/DirectX/length.ll
@@ -13,14 +13,6 @@ declare float @llvm.dx.length.v2f32(<2 x float>)
declare float @llvm.dx.length.v3f32(<3 x float>)
declare float @llvm.dx.length.v4f32(<4 x float>)
-define noundef half @test_length_half(half noundef %p0) {
-entry:
- ; EXPCHECK: call half @llvm.fabs.f16(half %{{.*}})
- ; DOPCHECK: call half @dx.op.unary.f16(i32 6, half %{{.*}})
- %0 = call half @llvm.fabs.f16(half %p0)
- ret half %0
-}
-
define noundef half @test_length_half2(<2 x half> noundef %p0) {
entry:
; CHECK: extractelement <2 x half> %{{.*}}, i64 0
@@ -72,15 +64,6 @@ entry:
ret half %hlsl.length
}
-define noundef float @test_length_float(float noundef %p0) {
-entry:
- ; EXPCHECK: call float @llvm.fabs.f32(float %p0)
- ; DOPCHECK: call float @dx.op.unary.f32(i32 6, float %{{.*}})
-
- %0 = call float @llvm.fabs.f32(float %p0)
- ret float %0
-}
-
define noundef float @test_length_float2(<2 x float> noundef %p0) {
entry:
; CHECK: extractelement <2 x float> %{{.*}}, i64 0
>From d04a06123b25578d67fe2ff8928edbb3d0cf2f5c Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 2 Aug 2024 16:04:20 -0700
Subject: [PATCH 12/13] add test for scalar inputs
---
.../CodeGen/DirectX/length_invalid_intrinsic_error.ll | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100644 llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error.ll
diff --git a/llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error.ll b/llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error.ll
new file mode 100644
index 0000000000000..ac3a0513eb6b2
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error.ll
@@ -0,0 +1,10 @@
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
+
+; DXIL operation length does not support scalar types
+; CHECK: error: invalid intrinsic signature
+
+define noundef float @test_length_float(float noundef %p0) {
+entry:
+ %hlsl.length = call float @llvm.dx.length.f32(float %p0)
+ ret float %hlsl.length
+}
>From dc3a89d0ef8839dc7f3f9e7ed96e47d94d76f149 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 2 Aug 2024 16:48:45 -0700
Subject: [PATCH 13/13] make an llvm error when length input is invalid
---
llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp | 5 +++--
.../CodeGen/DirectX/length_invalid_intrinsic_error.ll | 8 ++++----
.../DirectX/length_invalid_intrinsic_error_scalar.ll | 10 ++++++++++
3 files changed, 17 insertions(+), 6 deletions(-)
create mode 100644 llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error_scalar.ll
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index 501231298ed25..ac85859af8a53 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -171,8 +171,9 @@ static bool expandLengthIntrinsic(CallInst *Orig) {
Value *Elt = Builder.CreateExtractElement(X, (uint64_t)0);
auto *XVec = dyn_cast<FixedVectorType>(Ty);
unsigned XVecSize = XVec->getNumElements();
- assert(Ty->isVectorTy() && XVecSize > 1 &&
- "dx.length requires a vector of length 2 or more");
+ if (!(Ty->isVectorTy() && XVecSize > 1))
+ report_fatal_error(Twine("Invalid input type for length intrinsic"),
+ /* gen_crash_diag=*/false);
Value *Sum = Builder.CreateFMul(Elt, Elt);
for (unsigned I = 1; I < XVecSize; I++) {
diff --git a/llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error.ll b/llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error.ll
index ac3a0513eb6b2..277fbaa462b0f 100644
--- a/llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error.ll
+++ b/llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error.ll
@@ -1,10 +1,10 @@
; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
-; DXIL operation length does not support scalar types
-; CHECK: error: invalid intrinsic signature
+; DXIL operation length does not support 1-element vector types.
+; CHECK: LLVM ERROR: Invalid input type for length intrinsic
-define noundef float @test_length_float(float noundef %p0) {
+define noundef float @test_length_float(<1 x float> noundef %p0) {
entry:
- %hlsl.length = call float @llvm.dx.length.f32(float %p0)
+ %hlsl.length = call float @llvm.dx.length.v1f32(<1 x float> %p0)
ret float %hlsl.length
}
diff --git a/llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error_scalar.ll b/llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error_scalar.ll
new file mode 100644
index 0000000000000..ac3a0513eb6b2
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/length_invalid_intrinsic_error_scalar.ll
@@ -0,0 +1,10 @@
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
+
+; DXIL operation length does not support scalar types
+; CHECK: error: invalid intrinsic signature
+
+define noundef float @test_length_float(float noundef %p0) {
+entry:
+ %hlsl.length = call float @llvm.dx.length.f32(float %p0)
+ ret float %hlsl.length
+}
More information about the cfe-commits
mailing list