Skip to content

Commit 6f9a526

Browse files
committed
[clang][HLSL] Add sign intrinsic part 3
1 parent bdf0224 commit 6f9a526

File tree

7 files changed

+286
-0
lines changed

7 files changed

+286
-0
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4769,6 +4769,12 @@ def HLSLSelect : LangBuiltin<"HLSL_LANG"> {
47694769
let Prototype = "void(...)";
47704770
}
47714771

4772+
def HLSLSign : LangBuiltin<"HLSL_LANG"> {
4773+
let Spellings = ["__builtin_hlsl_elementwise_sign"];
4774+
let Attributes = [NoThrow, Const];
4775+
let Prototype = "void(...)";
4776+
}
4777+
47724778
// Builtins for XRay.
47734779
def XRayCustomEvent : Builtin {
47744780
let Spellings = ["__xray_customevent"];

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18870,6 +18870,23 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
1887018870
Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
1887118871
return EmitRuntimeCall(Intrinsic::getDeclaration(&CGM.getModule(), ID));
1887218872
}
18873+
case Builtin::BI__builtin_hlsl_elementwise_sign: {
18874+
Value *Op0 = EmitScalarExpr(E->getArg(0));
18875+
llvm::Type *Xty = Op0->getType();
18876+
llvm::Type *retType = llvm::Type::getInt32Ty(this->getLLVMContext());
18877+
if (Xty->isVectorTy()) {
18878+
auto *XVecTy = E->getArg(0)->getType()->getAs<VectorType>();
18879+
retType = llvm::VectorType::get(
18880+
retType, ElementCount::getFixed(XVecTy->getNumElements()));
18881+
}
18882+
assert((E->getArg(0)->getType()->hasFloatingRepresentation() ||
18883+
E->getArg(0)->getType()->hasSignedIntegerRepresentation()) &&
18884+
"sign operand must have a float or int representation");
18885+
18886+
return Builder.CreateIntrinsic(
18887+
retType, CGM.getHLSLRuntime().getSignIntrinsic(),
18888+
ArrayRef<Value *>{Op0}, nullptr, "hlsl.sign");
18889+
}
1887318890
}
1887418891
return nullptr;
1887518892
}

clang/lib/CodeGen/CGHLSLRuntime.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class CGHLSLRuntime {
8080
GENERATE_HLSL_INTRINSIC_FUNCTION(Normalize, normalize)
8181
GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt)
8282
GENERATE_HLSL_INTRINSIC_FUNCTION(Saturate, saturate)
83+
GENERATE_HLSL_INTRINSIC_FUNCTION(Sign, sign)
8384
GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
8485
GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
8586
GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1826,5 +1826,77 @@ _HLSL_AVAILABILITY(shadermodel, 6.0)
18261826
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_is_first_lane)
18271827
__attribute__((convergent)) bool WaveIsFirstLane();
18281828

1829+
//===----------------------------------------------------------------------===//
1830+
// sign builtins
1831+
//===----------------------------------------------------------------------===//
1832+
1833+
/// \fn T sign(T Val)
1834+
/// \brief Returns -1 if \a Val is less than zero; 0 if \a Val equals zero; and
1835+
/// 1 if \a Val is greater than zero. \param Val The input value.
1836+
1837+
#ifdef __HLSL_ENABLE_16_BIT
1838+
_HLSL_AVAILABILITY(shadermodel, 6.2)
1839+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1840+
int sign(int16_t);
1841+
_HLSL_AVAILABILITY(shadermodel, 6.2)
1842+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1843+
int2 sign(int16_t2);
1844+
_HLSL_AVAILABILITY(shadermodel, 6.2)
1845+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1846+
int3 sign(int16_t3);
1847+
_HLSL_AVAILABILITY(shadermodel, 6.2)
1848+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1849+
int4 sign(int16_t4);
1850+
#endif
1851+
1852+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
1853+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1854+
int sign(half);
1855+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
1856+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1857+
int2 sign(half2);
1858+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
1859+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1860+
int3 sign(half3);
1861+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
1862+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1863+
int4 sign(half4);
1864+
1865+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1866+
int sign(int);
1867+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1868+
int2 sign(int2);
1869+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1870+
int3 sign(int3);
1871+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1872+
int4 sign(int4);
1873+
1874+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1875+
int sign(float);
1876+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1877+
int2 sign(float2);
1878+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1879+
int3 sign(float3);
1880+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1881+
int4 sign(float4);
1882+
1883+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1884+
int sign(int64_t);
1885+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1886+
int2 sign(int64_t2);
1887+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1888+
int3 sign(int64_t3);
1889+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1890+
int4 sign(int64_t4);
1891+
1892+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1893+
int sign(double);
1894+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1895+
int2 sign(double2);
1896+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1897+
int3 sign(double3);
1898+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
1899+
int4 sign(double4);
1900+
>>>>>>> af4d3b4e2b22 ([clang][HLSL] Add sign intrinsic part 3)
18291901
} // namespace hlsl
18301902
#endif //_HLSL_HLSL_INTRINSICS_H_

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "clang/AST/Expr.h"
1717
#include "clang/AST/RecursiveASTVisitor.h"
1818
#include "clang/AST/Type.h"
19+
#include "clang/Basic/Builtins.h"
1920
#include "clang/Basic/DiagnosticSema.h"
2021
#include "clang/Basic/LLVM.h"
2122
#include "clang/Basic/SourceLocation.h"
@@ -1513,6 +1514,14 @@ bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall) {
15131514
return CheckArgsTypesAreCorrect(S, TheCall, S->Context.FloatTy,
15141515
checkDoubleVector);
15151516
}
1517+
bool CheckFloatingOrSignedIntRepresentation(Sema *S, CallExpr *TheCall) {
1518+
auto checkAllSignedTypes = [](clang::QualType PassedType) -> bool {
1519+
return !PassedType->hasSignedIntegerRepresentation() &&
1520+
!PassedType->hasFloatingRepresentation();
1521+
};
1522+
return CheckArgsTypesAreCorrect(S, TheCall, S->Context.IntTy,
1523+
checkAllSignedTypes);
1524+
}
15161525

15171526
bool CheckUnsignedIntRepresentation(Sema *S, CallExpr *TheCall) {
15181527
auto checkAllUnsignedTypes = [](clang::QualType PassedType) -> bool {
@@ -1726,6 +1735,14 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
17261735
TheCall->setType(ArgTyA);
17271736
break;
17281737
}
1738+
case Builtin::BI__builtin_hlsl_elementwise_sign: {
1739+
if (CheckFloatingOrSignedIntRepresentation(&SemaRef, TheCall))
1740+
return true;
1741+
if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))
1742+
return true;
1743+
SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().IntTy);
1744+
break;
1745+
}
17291746
// Note these are llvm builtins that we want to catch invalid intrinsic
17301747
// generation. Normal handling of these builitns will occur elsewhere.
17311748
case Builtin::BI__builtin_elementwise_bitreverse: {
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
2+
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
3+
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
4+
// RUN: --check-prefixes=CHECK,NATIVE_HALF \
5+
// RUN: -DTARGET=dx -DFNATTRS=noundef
6+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
7+
// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
8+
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
9+
// RUN: -DTARGET=dx -DFNATTRS=noundef
10+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
11+
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
12+
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
13+
// RUN: --check-prefixes=CHECK,NATIVE_HALF \
14+
// RUN: -DTARGET=spv -DFNATTRS="spir_func noundef"
15+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
16+
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
17+
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
18+
// RUN: -DTARGET=spv -DFNATTRS="spir_func noundef"
19+
20+
// NATIVE_HALF: define [[FNATTRS]] i32 @
21+
// NATIVE_HALF: %hlsl.sign = call i32 @llvm.[[TARGET]].sign.f16(
22+
// NATIVE_HALF: ret i32 %hlsl.sign
23+
// NO_HALF: define [[FNATTRS]] i32 @
24+
// NO_HALF: %hlsl.sign = call i32 @llvm.[[TARGET]].sign.f32(
25+
// NO_HALF: ret i32 %hlsl.sign
26+
int test_sign_half(half p0) { return sign(p0); }
27+
28+
// NATIVE_HALF: define [[FNATTRS]] <2 x i32> @
29+
// NATIVE_HALF: %hlsl.sign = call <2 x i32> @llvm.[[TARGET]].sign.v2f16(
30+
// NATIVE_HALF: ret <2 x i32> %hlsl.sign
31+
// NO_HALF: define [[FNATTRS]] <2 x i32> @
32+
// NO_HALF: %hlsl.sign = call <2 x i32> @llvm.[[TARGET]].sign.v2f32(
33+
// NO_HALF: ret <2 x i32> %hlsl.sign
34+
int2 test_sign_half2(half2 p0) { return sign(p0); }
35+
36+
// NATIVE_HALF: define [[FNATTRS]] <3 x i32> @
37+
// NATIVE_HALF: %hlsl.sign = call <3 x i32> @llvm.[[TARGET]].sign.v3f16(
38+
// NATIVE_HALF: ret <3 x i32> %hlsl.sign
39+
// NO_HALF: define [[FNATTRS]] <3 x i32> @
40+
// NO_HALF: %hlsl.sign = call <3 x i32> @llvm.[[TARGET]].sign.v3f32(
41+
// NO_HALF: ret <3 x i32> %hlsl.sign
42+
int3 test_sign_half3(half3 p0) { return sign(p0); }
43+
44+
// NATIVE_HALF: define [[FNATTRS]] <4 x i32> @
45+
// NATIVE_HALF: %hlsl.sign = call <4 x i32> @llvm.[[TARGET]].sign.v4f16(
46+
// NATIVE_HALF: ret <4 x i32> %hlsl.sign
47+
// NO_HALF: define [[FNATTRS]] <4 x i32> @
48+
// NO_HALF: %hlsl.sign = call <4 x i32> @llvm.[[TARGET]].sign.v4f32(
49+
// NO_HALF: ret <4 x i32> %hlsl.sign
50+
int4 test_sign_half4(half4 p0) { return sign(p0); }
51+
52+
53+
// CHECK: define [[FNATTRS]] i32 @
54+
// CHECK: %hlsl.sign = call i32 @llvm.[[TARGET]].sign.f32(
55+
// CHECK: ret i32 %hlsl.sign
56+
int test_sign_float(float p0) { return sign(p0); }
57+
58+
// CHECK: define [[FNATTRS]] <2 x i32> @
59+
// CHECK: %hlsl.sign = call <2 x i32> @llvm.[[TARGET]].sign.v2f32(
60+
// CHECK: ret <2 x i32> %hlsl.sign
61+
int2 test_sign_float2(float2 p0) { return sign(p0); }
62+
63+
// CHECK: define [[FNATTRS]] <3 x i32> @
64+
// CHECK: %hlsl.sign = call <3 x i32> @llvm.[[TARGET]].sign.v3f32(
65+
// CHECK: ret <3 x i32> %hlsl.sign
66+
int3 test_sign_float3(float3 p0) { return sign(p0); }
67+
68+
// CHECK: define [[FNATTRS]] <4 x i32> @
69+
// CHECK: %hlsl.sign = call <4 x i32> @llvm.[[TARGET]].sign.v4f32(
70+
// CHECK: ret <4 x i32> %hlsl.sign
71+
int4 test_sign_float4(float4 p0) { return sign(p0); }
72+
73+
74+
// CHECK: define [[FNATTRS]] i32 @
75+
// CHECK: %hlsl.sign = call i32 @llvm.[[TARGET]].sign.f64(
76+
// CHECK: ret i32 %hlsl.sign
77+
int test_sign_double(double p0) { return sign(p0); }
78+
79+
// CHECK: define [[FNATTRS]] <2 x i32> @
80+
// CHECK: %hlsl.sign = call <2 x i32> @llvm.[[TARGET]].sign.v2f64(
81+
// CHECK: ret <2 x i32> %hlsl.sign
82+
int2 test_sign_double2(double2 p0) { return sign(p0); }
83+
84+
// CHECK: define [[FNATTRS]] <3 x i32> @
85+
// CHECK: %hlsl.sign = call <3 x i32> @llvm.[[TARGET]].sign.v3f64(
86+
// CHECK: ret <3 x i32> %hlsl.sign
87+
int3 test_sign_double3(double3 p0) { return sign(p0); }
88+
89+
// CHECK: define [[FNATTRS]] <4 x i32> @
90+
// CHECK: %hlsl.sign = call <4 x i32> @llvm.[[TARGET]].sign.v4f64(
91+
// CHECK: ret <4 x i32> %hlsl.sign
92+
int4 test_sign_double4(double4 p0) { return sign(p0); }
93+
94+
95+
#ifdef __HLSL_ENABLE_16_BIT
96+
// NATIVE_HALF: define [[FNATTRS]] i32 @
97+
// NATIVE_HALF: %hlsl.sign = call i32 @llvm.[[TARGET]].sign.i16(
98+
// NATIVE_HALF: ret i32 %hlsl.sign
99+
int test_sign_int16_t(int16_t p0) { return sign(p0); }
100+
101+
// NATIVE_HALF: define [[FNATTRS]] <2 x i32> @
102+
// NATIVE_HALF: %hlsl.sign = call <2 x i32> @llvm.[[TARGET]].sign.v2i16(
103+
// NATIVE_HALF: ret <2 x i32> %hlsl.sign
104+
int2 test_sign_int16_t2(int16_t2 p0) { return sign(p0); }
105+
106+
// NATIVE_HALF: define [[FNATTRS]] <3 x i32> @
107+
// NATIVE_HALF: %hlsl.sign = call <3 x i32> @llvm.[[TARGET]].sign.v3i16(
108+
// NATIVE_HALF: ret <3 x i32> %hlsl.sign
109+
int3 test_sign_int16_t3(int16_t3 p0) { return sign(p0); }
110+
111+
// NATIVE_HALF: define [[FNATTRS]] <4 x i32> @
112+
// NATIVE_HALF: %hlsl.sign = call <4 x i32> @llvm.[[TARGET]].sign.v4i16(
113+
// NATIVE_HALF: ret <4 x i32> %hlsl.sign
114+
int4 test_sign_int16_t4(int16_t4 p0) { return sign(p0); }
115+
#endif // __HLSL_ENABLE_16_BIT
116+
117+
118+
// CHECK: define [[FNATTRS]] i32 @
119+
// CHECK: %hlsl.sign = call i32 @llvm.[[TARGET]].sign.i32(
120+
// CHECK: ret i32 %hlsl.sign
121+
int test_sign_int(int p0) { return sign(p0); }
122+
123+
// CHECK: define [[FNATTRS]] <2 x i32> @
124+
// CHECK: %hlsl.sign = call <2 x i32> @llvm.[[TARGET]].sign.v2i32(
125+
// CHECK: ret <2 x i32> %hlsl.sign
126+
int2 test_sign_int2(int2 p0) { return sign(p0); }
127+
128+
// CHECK: define [[FNATTRS]] <3 x i32> @
129+
// CHECK: %hlsl.sign = call <3 x i32> @llvm.[[TARGET]].sign.v3i32(
130+
// CHECK: ret <3 x i32> %hlsl.sign
131+
int3 test_sign_int3(int3 p0) { return sign(p0); }
132+
133+
// CHECK: define [[FNATTRS]] <4 x i32> @
134+
// CHECK: %hlsl.sign = call <4 x i32> @llvm.[[TARGET]].sign.v4i32(
135+
// CHECK: ret <4 x i32> %hlsl.sign
136+
int4 test_sign_int4(int4 p0) { return sign(p0); }
137+
138+
139+
// CHECK: define [[FNATTRS]] i32 @
140+
// CHECK: %hlsl.sign = call i32 @llvm.[[TARGET]].sign.i64(
141+
// CHECK: ret i32 %hlsl.sign
142+
int test_sign_int64_t(int64_t p0) { return sign(p0); }
143+
144+
// CHECK: define [[FNATTRS]] <2 x i32> @
145+
// CHECK: %hlsl.sign = call <2 x i32> @llvm.[[TARGET]].sign.v2i64(
146+
// CHECK: ret <2 x i32> %hlsl.sign
147+
int2 test_sign_int64_t2(int64_t2 p0) { return sign(p0); }
148+
149+
// CHECK: define [[FNATTRS]] <3 x i32> @
150+
// CHECK: %hlsl.sign = call <3 x i32> @llvm.[[TARGET]].sign.v3i64(
151+
// CHECK: ret <3 x i32> %hlsl.sign
152+
int3 test_sign_int64_t3(int64_t3 p0) { return sign(p0); }
153+
154+
// CHECK: define [[FNATTRS]] <4 x i32> @
155+
// CHECK: %hlsl.sign = call <4 x i32> @llvm.[[TARGET]].sign.v4i64(
156+
// CHECK: ret <4 x i32> %hlsl.sign
157+
int4 test_sign_int64_t4(int64_t4 p0) { return sign(p0); }
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected
2+
3+
bool test_too_few_arg() {
4+
return __builtin_hlsl_elementwise_sign();
5+
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
6+
}
7+
8+
bool2 test_too_many_arg(float2 p0) {
9+
return __builtin_hlsl_elementwise_sign(p0, p0);
10+
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
11+
}
12+
13+
bool builtin_bool_to_float_type_promotion(bool p1) {
14+
return __builtin_hlsl_elementwise_sign(p1);
15+
// expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}}
16+
}

0 commit comments

Comments
 (0)