diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 57705f2d2d0423..2449b90a0e7902 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18876,18 +18876,25 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { return EmitRuntimeCall(Intrinsic::getDeclaration(&CGM.getModule(), ID)); } case Builtin::BI__builtin_hlsl_elementwise_sign: { - Value *Op0 = EmitScalarExpr(E->getArg(0)); + auto *Arg0 = E->getArg(0); + Value *Op0 = EmitScalarExpr(Arg0); llvm::Type *Xty = Op0->getType(); llvm::Type *retType = llvm::Type::getInt32Ty(this->getLLVMContext()); if (Xty->isVectorTy()) { - auto *XVecTy = E->getArg(0)->getType()->getAs(); + auto *XVecTy = Arg0->getType()->getAs(); retType = llvm::VectorType::get( retType, ElementCount::getFixed(XVecTy->getNumElements())); } - assert((E->getArg(0)->getType()->hasFloatingRepresentation() || - E->getArg(0)->getType()->hasSignedIntegerRepresentation()) && + assert((Arg0->getType()->hasFloatingRepresentation() || + Arg0->getType()->hasIntegerRepresentation()) && "sign operand must have a float or int representation"); + if (Arg0->getType()->hasUnsignedIntegerRepresentation()) { + Value *Cmp = Builder.CreateICmpEQ(Op0, ConstantInt::get(Xty, 0)); + return Builder.CreateSelect(Cmp, ConstantInt::get(retType, 0), + ConstantInt::get(retType, 1), "hlsl.sign"); + } + return Builder.CreateIntrinsic( retType, CGM.getHLSLRuntime().getSignIntrinsic(), ArrayRef{Op0}, nullptr, "hlsl.sign"); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index f39a68ba847e98..813f8a317bf6bf 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -2088,6 +2088,19 @@ int3 sign(int16_t3); _HLSL_AVAILABILITY(shadermodel, 6.2) _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) int4 sign(int16_t4); + +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int sign(uint16_t); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int2 sign(uint16_t2); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int3 sign(uint16_t3); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int4 sign(uint16_t4); #endif _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) @@ -2112,6 +2125,15 @@ int3 sign(int3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) int4 sign(int4); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int sign(uint); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int2 sign(uint2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int3 sign(uint3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int4 sign(uint4); + _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) int sign(float); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) @@ -2130,6 +2152,15 @@ int3 sign(int64_t3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) int4 sign(int64_t4); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int sign(uint64_t); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int2 sign(uint64_t2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int3 sign(uint64_t3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) +int4 sign(uint64_t4); + _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) int sign(double); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index d2d2df829e7b11..05e6e7800112df 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1708,9 +1708,9 @@ static bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall) { return CheckArgsTypesAreCorrect(S, TheCall, S->Context.FloatTy, checkDoubleVector); } -static bool CheckFloatingOrSignedIntRepresentation(Sema *S, CallExpr *TheCall) { +static bool CheckFloatingOrIntRepresentation(Sema *S, CallExpr *TheCall) { auto checkAllSignedTypes = [](clang::QualType PassedType) -> bool { - return !PassedType->hasSignedIntegerRepresentation() && + return !PassedType->hasIntegerRepresentation() && !PassedType->hasFloatingRepresentation(); }; return CheckArgsTypesAreCorrect(S, TheCall, S->Context.IntTy, @@ -1966,7 +1966,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } case Builtin::BI__builtin_hlsl_elementwise_sign: { - if (CheckFloatingOrSignedIntRepresentation(&SemaRef, TheCall)) + if (CheckFloatingOrIntRepresentation(&SemaRef, TheCall)) return true; if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall)) return true; diff --git a/clang/test/CodeGenHLSL/builtins/sign.hlsl b/clang/test/CodeGenHLSL/builtins/sign.hlsl index 4bb239fb009e45..0ed9a9468d86c0 100644 --- a/clang/test/CodeGenHLSL/builtins/sign.hlsl +++ b/clang/test/CodeGenHLSL/builtins/sign.hlsl @@ -112,6 +112,27 @@ int3 test_sign_int16_t3(int16_t3 p0) { return sign(p0); } // NATIVE_HALF: %hlsl.sign = call <4 x i32> @llvm.[[TARGET]].sign.v4i16( // NATIVE_HALF: ret <4 x i32> %hlsl.sign int4 test_sign_int16_t4(int16_t4 p0) { return sign(p0); } + + +// NATIVE_HALF: define [[FNATTRS]] i32 @ +// NATIVE_HALF: [[CMP:%.*]] = icmp eq i16 [[ARG:%.*]], 0 +// NATIVE_HALF: %hlsl.sign = select i1 [[CMP]], i32 0, i32 1 +int test_sign_uint16_t(uint16_t p0) { return sign(p0); } + +// NATIVE_HALF: define [[FNATTRS]] <2 x i32> @ +// NATIVE_HALF: [[CMP:%.*]] = icmp eq <2 x i16> [[ARG:%.*]], zeroinitializer +// NATIVE_HALF: %hlsl.sign = select <2 x i1> [[CMP]], <2 x i32> zeroinitializer, <2 x i32> +int2 test_sign_uint16_t2(uint16_t2 p0) { return sign(p0); } + +// NATIVE_HALF: define [[FNATTRS]] <3 x i32> @ +// NATIVE_HALF: [[CMP:%.*]] = icmp eq <3 x i16> [[ARG:%.*]], zeroinitializer +// NATIVE_HALF: %hlsl.sign = select <3 x i1> [[CMP]], <3 x i32> zeroinitializer, <3 x i32> +int3 test_sign_uint16_t3(uint16_t3 p0) { return sign(p0); } + +// NATIVE_HALF: define [[FNATTRS]] <4 x i32> @ +// NATIVE_HALF: [[CMP:%.*]] = icmp eq <4 x i16> [[ARG:%.*]], zeroinitializer +// NATIVE_HALF: %hlsl.sign = select <4 x i1> [[CMP]], <4 x i32> zeroinitializer, <4 x i32> +int4 test_sign_uint16_t4(uint16_t4 p0) { return sign(p0); } #endif // __HLSL_ENABLE_16_BIT @@ -136,6 +157,27 @@ int3 test_sign_int3(int3 p0) { return sign(p0); } int4 test_sign_int4(int4 p0) { return sign(p0); } +// CHECK: define [[FNATTRS]] i32 @ +// CHECK: [[CMP:%.*]] = icmp eq i32 [[ARG:%.*]], 0 +// CHECK: %hlsl.sign = select i1 [[CMP]], i32 0, i32 1 +int test_sign_uint(uint p0) { return sign(p0); } + +// CHECK: define [[FNATTRS]] <2 x i32> @ +// CHECK: [[CMP:%.*]] = icmp eq <2 x i32> [[ARG:%.*]], zeroinitializer +// CHECK: %hlsl.sign = select <2 x i1> [[CMP]], <2 x i32> zeroinitializer, <2 x i32> +int2 test_sign_uint2(uint2 p0) { return sign(p0); } + +// CHECK: define [[FNATTRS]] <3 x i32> @ +// CHECK: [[CMP:%.*]] = icmp eq <3 x i32> [[ARG:%.*]], zeroinitializer +// CHECK: %hlsl.sign = select <3 x i1> [[CMP]], <3 x i32> zeroinitializer, <3 x i32> +int3 test_sign_uint3(uint3 p0) { return sign(p0); } + +// CHECK: define [[FNATTRS]] <4 x i32> @ +// CHECK: [[CMP:%.*]] = icmp eq <4 x i32> [[ARG:%.*]], zeroinitializer +// CHECK: %hlsl.sign = select <4 x i1> [[CMP]], <4 x i32> zeroinitializer, <4 x i32> +int4 test_sign_uint4(uint4 p0) { return sign(p0); } + + // CHECK: define [[FNATTRS]] i32 @ // CHECK: %hlsl.sign = call i32 @llvm.[[TARGET]].sign.i64( // CHECK: ret i32 %hlsl.sign @@ -155,3 +197,24 @@ int3 test_sign_int64_t3(int64_t3 p0) { return sign(p0); } // CHECK: %hlsl.sign = call <4 x i32> @llvm.[[TARGET]].sign.v4i64( // CHECK: ret <4 x i32> %hlsl.sign int4 test_sign_int64_t4(int64_t4 p0) { return sign(p0); } + + +// CHECK: define [[FNATTRS]] i32 @ +// CHECK: [[CMP:%.*]] = icmp eq i64 [[ARG:%.*]], 0 +// CHECK: %hlsl.sign = select i1 [[CMP]], i32 0, i32 1 +int test_sign_int64_t(uint64_t p0) { return sign(p0); } + +// CHECK: define [[FNATTRS]] <2 x i32> @ +// CHECK: [[CMP:%.*]] = icmp eq <2 x i64> [[ARG:%.*]], zeroinitializer +// CHECK: %hlsl.sign = select <2 x i1> [[CMP]], <2 x i32> zeroinitializer, <2 x i32> +int2 test_sign_int64_t2(uint64_t2 p0) { return sign(p0); } + +// CHECK: define [[FNATTRS]] <3 x i32> @ +// CHECK: [[CMP:%.*]] = icmp eq <3 x i64> [[ARG:%.*]], zeroinitializer +// CHECK: %hlsl.sign = select <3 x i1> [[CMP]], <3 x i32> zeroinitializer, <3 x i32> +int3 test_sign_int64_t3(uint64_t3 p0) { return sign(p0); } + +// CHECK: define [[FNATTRS]] <4 x i32> @ +// CHECK: [[CMP:%.*]] = icmp eq <4 x i64> [[ARG:%.*]], zeroinitializer +// CHECK: %hlsl.sign = select <4 x i1> [[CMP]], <4 x i32> zeroinitializer, <4 x i32> +int4 test_sign_int64_t4(uint64_t4 p0) { return sign(p0); }