https://github.com/Alexander-Johnston updated https://github.com/llvm/llvm-project/pull/224277
>From 4b85318bf69c6e78fa29b72494fe9dba1b591aa7 Mon Sep 17 00:00:00 2001 From: Alexander Johnston <[email protected]> Date: Thu, 17 Sep 2026 12:32:44 +0100 Subject: [PATCH 1/3] [HLSL] Introduce HLSL packed types used by pack_ and unpack_ This introduces the HLSL types int8_t4_packe and uint8_t4_packed. These types are implicitly converted to uint as described by the DirectX specs, but have not been given the full breadth of functionality DXC provides them (such as increment operations). --- clang/include/clang/AST/ASTContext.h | 2 + clang/include/clang/AST/TypeBase.h | 21 +++++++++- clang/include/clang/AST/TypeProperties.td | 4 ++ clang/include/clang/Basic/HLSLIntrinsics.td | 2 + clang/include/clang/Basic/HLSLPackedTypes.def | 31 +++++++++++++++ clang/include/clang/Basic/Specifiers.h | 3 ++ clang/include/clang/Basic/TokenKinds.def | 3 ++ clang/include/clang/Sema/DeclSpec.h | 3 ++ clang/include/clang/Sema/Overload.h | 3 ++ clang/include/clang/Sema/SemaHLSL.h | 1 + .../include/clang/Serialization/ASTBitCodes.h | 5 ++- clang/lib/AST/ASTContext.cpp | 15 +++++++ clang/lib/AST/ASTImporter.cpp | 4 ++ clang/lib/AST/ExprConstant.cpp | 2 + clang/lib/AST/ItaniumMangle.cpp | 5 +++ clang/lib/AST/MicrosoftMangle.cpp | 6 +++ clang/lib/AST/NSAPI.cpp | 2 + clang/lib/AST/PrintfFormatString.cpp | 3 ++ clang/lib/AST/Type.cpp | 8 ++++ clang/lib/AST/TypeLoc.cpp | 2 + clang/lib/CodeGen/CGDebugInfo.cpp | 4 ++ clang/lib/CodeGen/CGDebugInfo.h | 3 ++ clang/lib/CodeGen/CodeGenTypes.cpp | 4 ++ clang/lib/CodeGen/ItaniumCXXABI.cpp | 2 + clang/lib/CodeGen/QualTypeMapper.cpp | 4 ++ clang/lib/Parse/ParseDecl.cpp | 13 +++++++ clang/lib/Parse/ParseExpr.cpp | 2 + clang/lib/Parse/ParseExprCXX.cpp | 5 +++ clang/lib/Parse/ParseTentative.cpp | 4 ++ clang/lib/Sema/DeclSpec.cpp | 6 +++ clang/lib/Sema/SemaCast.cpp | 9 +++++ clang/lib/Sema/SemaExpr.cpp | 4 ++ clang/lib/Sema/SemaExprCXX.cpp | 13 ++++++- clang/lib/Sema/SemaHLSL.cpp | 9 +++++ clang/lib/Sema/SemaOverload.cpp | 39 +++++++++++++++++++ clang/lib/Sema/SemaTemplateVariadic.cpp | 2 + clang/lib/Sema/SemaType.cpp | 6 +++ clang/lib/Serialization/ASTCommon.cpp | 5 +++ clang/lib/Serialization/ASTReader.cpp | 5 +++ .../UnifiedSymbolResolution/USRGeneration.cpp | 5 +++ clang/test/AST/HLSL/int8_t4_packed.hlsl | 8 ++++ clang/test/AST/HLSL/uint8_t4_packed.hlsl | 8 ++++ .../test/SemaHLSL/BuiltIns/packed-types.hlsl | 20 ++++++++++ .../SemaHLSL/Types/int8_t4_packed-size.hlsl | 5 +++ .../SemaHLSL/Types/uint8_t4_packed-size.hlsl | 5 +++ clang/tools/libclang/CIndex.cpp | 2 + 46 files changed, 314 insertions(+), 3 deletions(-) create mode 100644 clang/include/clang/Basic/HLSLPackedTypes.def create mode 100644 clang/test/AST/HLSL/int8_t4_packed.hlsl create mode 100644 clang/test/AST/HLSL/uint8_t4_packed.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/packed-types.hlsl create mode 100644 clang/test/SemaHLSL/Types/int8_t4_packed-size.hlsl create mode 100644 clang/test/SemaHLSL/Types/uint8_t4_packed-size.hlsl diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 2f7d39599c477..d686b0ae9f95e 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1422,6 +1422,8 @@ class ASTContext : public RefCountedBase<ASTContext> { #include "clang/Basic/AMDGPUTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) CanQualType SingletonId; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) CanQualType SingletonId; +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) CanQualType SingletonId; #include "clang/Basic/SPIRVTypes.def" diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index 424a2afee84da..040e593cd8ba0 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -2796,8 +2796,11 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) bool is##Id##Type() const; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) bool is##Id##Type() const; +#include "clang/Basic/HLSLPackedTypes.def" bool isHLSLSpecificType() const; // Any HLSL specific type bool isHLSLBuiltinIntangibleType() const; // Any HLSL builtin intangible type + bool isHLSLBuiltinPackedType() const; bool isHLSLAttributedResourceType() const; bool isHLSLInlineSpirvType() const; bool isHLSLResourceRecord() const; @@ -3265,6 +3268,9 @@ class BuiltinType : public Type { // HLSL intangible Types #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) Id, #include "clang/Basic/HLSLIntangibleTypes.def" +// HLSL intangible Types +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) Id, +#include "clang/Basic/HLSLPackedTypes.def" // SPIRV types #define SPIRV_TYPE(Name, Id, SingletonId) Id, #include "clang/Basic/SPIRVTypes.def" @@ -8960,6 +8966,12 @@ inline bool Type::isOpenCLSpecificType() const { } #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + inline bool Type::is##Id##Type() const { \ + return isSpecificBuiltinType(BuiltinType::Id); \ + } +#include "clang/Basic/HLSLPackedTypes.def" + #define SPIRV_TYPE(Name, Id, SingletonId) \ inline bool Type::is##Id##Type() const { \ return isSpecificBuiltinType(BuiltinType::Id); \ @@ -8973,9 +8985,16 @@ inline bool Type::isHLSLBuiltinIntangibleType() const { false; } +inline bool Type::isHLSLBuiltinPackedType() const { +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) is##Id##Type() || + return +#include "clang/Basic/HLSLPackedTypes.def" + false; +} + inline bool Type::isHLSLSpecificType() const { return isHLSLBuiltinIntangibleType() || isHLSLAttributedResourceType() || - isHLSLInlineSpirvType(); + isHLSLInlineSpirvType() || isHLSLBuiltinPackedType(); } inline bool Type::isHLSLAttributedResourceType() const { diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td index dc2a45ec85729..c6e494ddb75c1 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -885,6 +885,10 @@ let Class = BuiltinType in { case BuiltinType::ID: return ctx.SINGLETON_ID; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(NAME, ID, SINGLETON_ID) \ + case BuiltinType::ID: return ctx.SINGLETON_ID; +#include "clang/Basic/HLSLPackedTypes.def" + #define SPIRV_TYPE(NAME, ID, SINGLETON_ID) \ case BuiltinType::ID: return ctx.SINGLETON_ID; #include "clang/Basic/SPIRVTypes.def" diff --git a/clang/include/clang/Basic/HLSLIntrinsics.td b/clang/include/clang/Basic/HLSLIntrinsics.td index 21c0960b6fa23..163a51dd9497e 100644 --- a/clang/include/clang/Basic/HLSLIntrinsics.td +++ b/clang/include/clang/Basic/HLSLIntrinsics.td @@ -65,6 +65,8 @@ def IntTy : HLSLType<"int">; def UIntTy : HLSLType<"uint">; def Int64Ty : HLSLType<"int64_t">; def UInt64Ty : HLSLType<"uint64_t">; +def Int8PackedTy : HLSLType<"int8_t4_packed">; +def UInt8PackedTy : HLSLType<"uint8_t4_packed">; //===----------------------------------------------------------------------===// // Element type groups diff --git a/clang/include/clang/Basic/HLSLPackedTypes.def b/clang/include/clang/Basic/HLSLPackedTypes.def new file mode 100644 index 0000000000000..763267bb779eb --- /dev/null +++ b/clang/include/clang/Basic/HLSLPackedTypes.def @@ -0,0 +1,31 @@ +//===-- HLSLPackedTypes.def - HLSL packed scalar types ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines HLSL SM 6.6 packed types. +// +// The macro is: +// +// HLSL_PACKED_TYPE(Spelling, Id, SingletonId) +// +// where: +// +// - Spelling is the HLSL type name (e.g. int8_t4_packed). +// +// - BuiltinType::Id is the enumerator defining the type. +// +// - Context.SingletonId is the global singleton of this type. +// +// To include this file, define HLSL_PACKED_TYPE. +// The macro will be undefined after inclusion. +// +//===----------------------------------------------------------------------===// + +HLSL_PACKED_TYPE(int8_t4_packed, Int8_4Packed, Int8_4PackedTy) +HLSL_PACKED_TYPE(uint8_t4_packed, UInt8_4Packed, UInt8_4PackedTy) + +#undef HLSL_PACKED_TYPE diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index c1b7198565f07..67742038bb6a8 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -102,6 +102,9 @@ namespace clang { #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \ TST_##Name, // HLSL Intangible Types #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + TST_##Name, // HLSL Packed Types +#include "clang/Basic/HLSLPackedTypes.def" TST_error // erroneous type }; diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index dc9c7d8109467..97e5915bcd0d5 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -552,6 +552,9 @@ KEYWORD(column_major , KEYHLSL) // HLSL Intangible Types #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) KEYWORD(Name, KEYHLSL) #include "clang/Basic/HLSLIntangibleTypes.def" +// HLSL Packed Types +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) KEYWORD(Name, KEYHLSL) +#include "clang/Basic/HLSLPackedTypes.def" // Borland Extensions. KEYWORD(__pascal , KEYALL) diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index e6dc6831d893f..66a6098a75ae9 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -298,6 +298,9 @@ class DeclSpec { #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \ static const TST TST_##Name = clang::TST_##Name; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + static const TST TST_##Name = clang::TST_##Name; +#include "clang/Basic/HLSLPackedTypes.def" static const TST TST_error = clang::TST_error; // type-qualifiers diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 3abc0013d8f69..af3335f5b53ee 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -210,6 +210,9 @@ class Sema; /// HLSL matrix splat from scalar or boolean type. ICK_HLSL_Matrix_Splat, + /// HLSL packed type conversion to uint + ICK_HLSL_Packed_Type_Conversion, + /// The number of conversion kinds ICK_Num_Conversion_Kinds, }; diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 6c0e5b52f7cb3..6096f24b25069 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -239,6 +239,7 @@ class SemaHLSL : public SemaBase { bool CanPerformScalarCast(QualType SrcTy, QualType DestTy); bool CanPerformElementwiseCast(Expr *Src, QualType DestType); bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType); + bool CanPerformPackedToUintCast(Expr *SrcTy, QualType DestTy); ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg); QualType getInoutParameterType(QualType Ty); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 6a52a9e4fa780..5dd6f38d64f37 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1154,6 +1154,9 @@ enum PredefinedTypeIDs { // \brief HLSL intangible types with auto numeration #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID, #include "clang/Basic/HLSLIntangibleTypes.def" +// \brief HLSL packed types with auto numeration +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID, +#include "clang/Basic/HLSLPackedTypes.def" // \brief SPIR-V types with auto numeration #define SPIRV_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID, #include "clang/Basic/SPIRVTypes.def" @@ -1169,7 +1172,7 @@ enum PredefinedTypeIDs { /// /// Type IDs for non-predefined types will start at /// NUM_PREDEF_TYPE_IDs. -const unsigned NUM_PREDEF_TYPE_IDS = 530; +const unsigned NUM_PREDEF_TYPE_IDS = 532; // Ensure we do not overrun the predefined types we reserved // in the enum PredefinedTypeIDs above. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index ef3e6e87ec1fe..6533c82c1c12f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1448,6 +1448,10 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \ InitBuiltinType(SingletonId, BuiltinType::Id); #include "clang/Basic/HLSLIntangibleTypes.def" + +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + InitBuiltinType(SingletonId, BuiltinType::Id); +#include "clang/Basic/HLSLPackedTypes.def" } if (Target.hasAArch64ACLETypes() || @@ -2452,6 +2456,11 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = Target->getPointerWidth(LangAS::Default); Align = Target->getPointerAlign(LangAS::Default); break; +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" + Width = 32; + Align = 32; + break; #define SPIRV_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: \ Width = Target->getPointerWidth(LangAS::Default); \ @@ -3604,6 +3613,10 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, case BuiltinType::Id: \ return; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + return; +#include "clang/Basic/HLSLPackedTypes.def" case BuiltinType::Dependent: llvm_unreachable("should never get here"); #define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id: @@ -9274,6 +9287,8 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C, #include "clang/Basic/PPCTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" #define BUILTIN_TYPE(KIND, ID) #define PLACEHOLDER_TYPE(KIND, ID) \ case BuiltinType::KIND: diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 22c3af47f451f..7871ff717fe99 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1370,6 +1370,10 @@ ExpectedType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { case BuiltinType::Id: \ return Importer.getToContext().SingletonId; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + return Importer.getToContext().SingletonId; +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: \ return Importer.getToContext().SingletonId; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 9242491832841..2b6b087c7652c 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -16384,6 +16384,8 @@ GCCTypeClass EvaluateBuiltinClassifyType(QualType T, #include "clang/Basic/AMDGPUTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/SPIRVTypes.def" return GCCTypeClass::None; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 780fe3a321200..e25a61dc1e69a 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3564,6 +3564,11 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { mangleVendorType(#Name); \ break; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + mangleVendorType(#Name); \ + break; +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: \ mangleVendorType(Name); \ diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index cc7bf2279b72e..983306e422485 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -2833,6 +2833,12 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, break; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + mangleArtificialTagType(TagTypeKind::Struct, #Name); \ + break; +#include "clang/Basic/HLSLPackedTypes.def" + case BuiltinType::SveBool: Out << "$_CA"; break; diff --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp index 7142ded5a551d..54c0b03b14848 100644 --- a/clang/lib/AST/NSAPI.cpp +++ b/clang/lib/AST/NSAPI.cpp @@ -457,6 +457,8 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { #include "clang/Basic/AMDGPUTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/SPIRVTypes.def" case BuiltinType::BoundMember: diff --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp index e0cff04069d59..d09ed5e02dc02 100644 --- a/clang/lib/AST/PrintfFormatString.cpp +++ b/clang/lib/AST/PrintfFormatString.cpp @@ -957,6 +957,9 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" + #define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/SPIRVTypes.def" diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index cbacca1c44d91..9059272056809 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2507,6 +2507,8 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const { return STK_Floating; if (BT->isFixedPointType()) return STK_FixedPoint; + if (BT->isHLSLBuiltinPackedType()) + return STK_Integral; llvm_unreachable("unknown scalar builtin type"); } else if (isa<PointerType>(T)) { return STK_CPointer; @@ -3708,6 +3710,10 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { case Id: \ return #Name; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case Id: \ + return #Name; +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) \ case Id: \ return Name; @@ -5281,6 +5287,8 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { #include "clang/Basic/AMDGPUTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/SPIRVTypes.def" case BuiltinType::BuiltinFn: diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index 682ce9ffacc30..da7e130f6d813 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -421,6 +421,8 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { #include "clang/Basic/AMDGPUTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/SPIRVTypes.def" case BuiltinType::BuiltinFn: diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 02864621d60a3..e3f68c058838d 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -979,6 +979,10 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { case BuiltinType::Id: \ return getOrCreateStructPtrType(#Name, SingletonId); #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + return DBuilder.createBasicType(#Name, 32, llvm::dwarf::DW_ATE_unsigned); +#include "clang/Basic/HLSLPackedTypes.def" #define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/AArch64ACLETypes.def" diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 8a46e3f0e60bb..37520394812b4 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -97,6 +97,9 @@ class CGDebugInfo { #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \ llvm::DIType *SingletonId = nullptr; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + llvm::DIType *SingletonId = nullptr; +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) llvm::DIType *SingletonId = nullptr; #include "clang/Basic/SPIRVTypes.def" diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 99ead1295bc58..facd551f9a604 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -590,6 +590,10 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { #include "clang/Basic/HLSLIntangibleTypes.def" ResultType = CGM.getHLSLRuntime().convertHLSLSpecificType(Ty); break; +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" + ResultType = llvm::IntegerType::get(getLLVMContext(), 32); + break; #define SPIRV_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: \ return llvm::TargetExtType::get(getLLVMContext(), "spirv.Event"); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index c17813140b10f..b4b5fb5d7fd20 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3787,6 +3787,8 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { #include "clang/Basic/AMDGPUTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/SPIRVTypes.def" case BuiltinType::ShortAccum: diff --git a/clang/lib/CodeGen/QualTypeMapper.cpp b/clang/lib/CodeGen/QualTypeMapper.cpp index a6e96c63446f6..dd8dd6a571891 100644 --- a/clang/lib/CodeGen/QualTypeMapper.cpp +++ b/clang/lib/CodeGen/QualTypeMapper.cpp @@ -311,6 +311,10 @@ QualTypeMapper::convertBuiltinType(const BuiltinType *BT) { #include "clang/Basic/HLSLIntangibleTypes.def" llvm::reportFatalInternalError( "HLSL intangible types not yet Supported in ABI lowering library"); +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" + llvm::reportFatalInternalError( + "HLSL packed types not yet Supported in ABI lowering library"); #define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/SPIRVTypes.def" llvm::reportFatalInternalError( diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index a4bdec00ca80a..0d0a193e7bd88 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4672,6 +4672,13 @@ void Parser::ParseDeclarationSpecifiers( break; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case tok::kw_##Name: \ + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_##Name, Loc, PrevSpec, \ + DiagID, Policy); \ + break; +#include "clang/Basic/HLSLPackedTypes.def" + case tok::less: // GCC ObjC supports types like "<SomeProtocol>" as a synonym for // "id<SomeProtocol>". This is hopelessly old fashioned and dangerous, @@ -5612,6 +5619,8 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { #include "clang/Basic/OpenCLImageTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name: +#include "clang/Basic/HLSLPackedTypes.def" // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: @@ -5702,6 +5711,8 @@ bool Parser::isTypeSpecifierQualifier(const Token &Tok) { #include "clang/Basic/OpenCLImageTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name: +#include "clang/Basic/HLSLPackedTypes.def" // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: @@ -6048,6 +6059,8 @@ bool Parser::isDeclarationSpecifier( #include "clang/Basic/OpenCLImageTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name: +#include "clang/Basic/HLSLPackedTypes.def" case tok::kw___funcref: case tok::kw_groupshared: diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index ef89b77d0a997..05cb680faa215 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1354,6 +1354,8 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, #include "clang/Basic/OpenCLImageTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name: +#include "clang/Basic/HLSLPackedTypes.def" { if (!getLangOpts().CPlusPlus) { Diag(Tok, diag::err_expected_expression); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 860c069e18fca..6542fc10e23d9 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -2218,6 +2218,11 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { DS.SetTypeSpecType(DeclSpec::TST_##Name, Loc, PrevSpec, DiagID, Policy); \ break; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case tok::kw_##Name: \ + DS.SetTypeSpecType(DeclSpec::TST_##Name, Loc, PrevSpec, DiagID, Policy); \ + break; +#include "clang/Basic/HLSLPackedTypes.def" case tok::annot_decltype: case tok::kw_decltype: diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index c71ce09267f8a..efbb1ecd5abb4 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1527,6 +1527,8 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename, #include "clang/Basic/OpenCLImageTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name: +#include "clang/Basic/HLSLPackedTypes.def" if (NextToken().is(tok::l_paren)) return TPResult::Ambiguous; @@ -1657,6 +1659,8 @@ bool Parser::isCXXDeclarationSpecifierAType() { #include "clang/Basic/OpenCLImageTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name: +#include "clang/Basic/HLSLPackedTypes.def" return true; case tok::kw_auto: diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index c13d5c8345604..1bc3bb45dc897 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -350,6 +350,8 @@ bool Declarator::isDeclarationOfFunction() const { #include "clang/Basic/OpenCLImageTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case TST_##Name: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case TST_##Name: +#include "clang/Basic/HLSLPackedTypes.def" return false; case TST_decltype_auto: @@ -585,6 +587,10 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, case DeclSpec::TST_##Name: \ return #Name; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case DeclSpec::TST_##Name: \ + return #Name; +#include "clang/Basic/HLSLPackedTypes.def" case DeclSpec::TST_error: return "(error)"; } llvm_unreachable("Unknown typespec!"); diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index cc76411135d23..f2dc0f79c6e95 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -2977,6 +2977,15 @@ bool CastOperation::CheckHLSLCStyleCast(CheckedConversionKind CCK) { return true; } + // HLSL includes packed data types that can be converted directly to uint + if (Self.HLSL().CanPerformPackedToUintCast(SrcExpr.get(), DestType)) { + SrcExpr = Self.ImpCastExprToType( + SrcExpr.get(), SrcExpr.get()->getType(), CK_IntegralCast, + SrcExpr.get()->getValueKind(), nullptr, CCK); + Kind = CK_IntegralCast; + return true; + } + // If the destination is an array, we've exhausted the valid HLSL casts, so we // should emit a dignostic and stop processing. if (DestType->isArrayType()) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 7444fe0e71fd8..e7103f8c98a96 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6514,6 +6514,8 @@ static bool isPlaceholderToRemoveAsArg(QualType type) { #include "clang/Basic/AMDGPUTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/SPIRVTypes.def" #define PLACEHOLDER_TYPE(ID, SINGLETON_ID) @@ -22255,6 +22257,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { #include "clang/Basic/AMDGPUTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/SPIRVTypes.def" #define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id: diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index deb7bdd09fdc7..242d78a4ef9c3 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5007,6 +5007,15 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, llvm_unreachable("Improper first standard conversion"); } + // HLSL Packed Types are a special case which need to be converted to uint + // before the second conversions are applied. + if (SCS.Dimension == ICK_HLSL_Packed_Type_Conversion) { + From = ImpCastExprToType(From, Context.UnsignedIntTy, CK_IntegralCast, + From->getValueKind(), nullptr, CCK) + .get(); + FromType = Context.UnsignedIntTy; + } + // Perform the second implicit conversion switch (SCS.Second) { case ICK_Identity: @@ -5411,10 +5420,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, case ICK_HLSL_Matrix_Truncation: case ICK_HLSL_Vector_Splat: case ICK_HLSL_Matrix_Splat: + case ICK_HLSL_Packed_Type_Conversion: llvm_unreachable("Improper second standard conversion"); } - if (SCS.Dimension != ICK_Identity) { + if (SCS.Dimension != ICK_Identity && + SCS.Dimension != ICK_HLSL_Packed_Type_Conversion) { // If SCS.Element is not ICK_Identity the To and From types must be HLSL // vectors or matrices. assert( diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 461bb8fb96678..f0e71297cf4b2 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -5184,6 +5184,15 @@ bool SemaHLSL::CanPerformElementwiseCast(Expr *Src, QualType DestTy) { return true; } +bool SemaHLSL::CanPerformPackedToUintCast(Expr *Src, QualType DestTy) { + QualType SrcTy = Src->getType(); + if (SrcTy->isHLSLBuiltinPackedType()) { + if (DestTy->isScalarType() || DestTy->isHLSLBuiltinPackedType()) + return true; + } + return false; +} + ExprResult SemaHLSL::ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg) { assert(Param->hasAttr<HLSLParamModifierAttr>() && "We should not get here without a parameter modifier expression"); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 963f0e93bd651..ebd8e4630323a 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -196,6 +196,7 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) { ICR_Conversion, ICR_HLSL_Scalar_Widening, ICR_HLSL_Scalar_Widening, + ICR_HLSL_Dimension_Reduction, }; static_assert(std::size(Rank) == (int)ICK_Num_Conversion_Kinds); return Rank[(int)Kind]; @@ -260,6 +261,7 @@ static const char *GetImplicitConversionName(ImplicitConversionKind Kind) { "Non-decaying array conversion", "HLSL vector splat", "HLSL matrix splat", + "HLSL packed type conversion", }; static_assert(std::size(Name) == (int)ICK_Num_Conversion_Kinds); return Name[Kind]; @@ -2345,6 +2347,37 @@ static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType, return false; } +static bool IsHLSLPackedTypeConversion(Sema &S, QualType FromType, + QualType ToType, + ImplicitConversionKind &ICK, + ImplicitConversionKind &DimensionICK, + Expr *From) { + if (!S.getLangOpts().HLSL || !FromType->isHLSLBuiltinPackedType()) + return false; + if (S.Context.hasSameUnqualifiedType(FromType, ToType)) + return false; + + if (ToType->isHLSLBuiltinPackedType()) { + ICK = ICK_Integral_Conversion; + DimensionICK = ICK_Identity; + return true; + } + + if (!ToType->isScalarType()) + return false; + + QualType UIntTy = S.Context.UnsignedIntTy; + DimensionICK = ICK_HLSL_Packed_Type_Conversion; + + // Already converting to uint, don't need to do anything else + if (S.Context.hasSameUnqualifiedType(UIntTy, ToType)) + return true; + + // We can reuse IsVectorOrMatrixElementConversion to handle uint to + // float/integral/boolean conversion and promotion + return IsVectorOrMatrixElementConversion(S, UIntTy, ToType, ICK, From); +} + static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType, bool InOverloadResolution, StandardConversionSequence &SCS, @@ -2612,6 +2645,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, SCS.Second = SecondICK; SCS.Dimension = DimensionICK; FromType = ToType.getUnqualifiedType(); + } else if (IsHLSLPackedTypeConversion(S, FromType, ToType, SecondICK, + DimensionICK, From)) { + SCS.Second = SecondICK; + SCS.Dimension = DimensionICK; + FromType = ToType.getUnqualifiedType(); } else if (!S.getLangOpts().CPlusPlus && S.Context.typesAreCompatible(ToType, FromType)) { // Compatible conversions (Clang extension for C function overloading) @@ -6497,6 +6535,7 @@ static bool CheckConvertedConstantConversions(Sema &S, case ICK_Array_To_Pointer: case ICK_Function_To_Pointer: case ICK_HLSL_Array_RValue: + case ICK_HLSL_Packed_Type_Conversion: llvm_unreachable("found a first conversion kind in Second"); case ICK_Function_Conversion: diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 0f5c4d41c3295..7f6cd7f6e7ce6 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -1210,6 +1210,8 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { #include "clang/Basic/OpenCLImageTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case TST_##Name: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case TST_##Name: +#include "clang/Basic/HLSLPackedTypes.def" case TST_unknown_anytype: case TST_error: break; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 483f9ab088799..9b2b6c9f64641 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1394,6 +1394,12 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { break; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case DeclSpec::TST_##Name: \ + Result = Context.SingletonId; \ + break; +#include "clang/Basic/HLSLPackedTypes.def" + case DeclSpec::TST_error: Result = Context.IntTy; declarator.setInvalidType(true); diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index ca7993adb7d2c..6b107fae054f2 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -268,6 +268,11 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { ID = PREDEF_TYPE_##Id##_ID; \ break; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + ID = PREDEF_TYPE_##Id##_ID; \ + break; +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: \ ID = PREDEF_TYPE_##Id##_ID; \ diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index a9c230d767c50..2b9950c7f4cbb 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -8171,6 +8171,11 @@ QualType ASTReader::GetType(TypeID ID) { T = Context.SingletonId; \ break; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case PREDEF_TYPE_##Id##_ID: \ + T = Context.SingletonId; \ + break; +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) \ case PREDEF_TYPE_##Id##_ID: \ T = Context.SingletonId; \ diff --git a/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp b/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp index 19f3fa19efb27..cab4520dc57e4 100644 --- a/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp +++ b/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp @@ -858,6 +858,11 @@ void USRGenerator::VisitType(QualType T) { Out << "@BT@" << #Name; \ break; #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + Out << "@BT@" << #Name; \ + break; +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: \ Out << "@BT@" << Name; \ diff --git a/clang/test/AST/HLSL/int8_t4_packed.hlsl b/clang/test/AST/HLSL/int8_t4_packed.hlsl new file mode 100644 index 0000000000000..16c33d71086f4 --- /dev/null +++ b/clang/test/AST/HLSL/int8_t4_packed.hlsl @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -x hlsl -ast-dump -disable-llvm-passes -o - 2>&1 %s | FileCheck %s + +struct MyBuffer { + int8_t4_packed val; +}; + +// CHECK:CXXRecordDecl 0x{{[0-9a-z]+}} <{{.*}}> line:3:8 struct MyBuffer definition +// CHECK:FieldDecl 0x{{[0-9a-z]+}} <line:4:3, col:18> col:18 val 'int8_t4_packed' diff --git a/clang/test/AST/HLSL/uint8_t4_packed.hlsl b/clang/test/AST/HLSL/uint8_t4_packed.hlsl new file mode 100644 index 0000000000000..3b18bf6bb9d52 --- /dev/null +++ b/clang/test/AST/HLSL/uint8_t4_packed.hlsl @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -x hlsl -ast-dump -disable-llvm-passes -o - 2>&1 %s | FileCheck %s + +struct MyBuffer { + uint8_t4_packed val; +}; + +// CHECK:CXXRecordDecl 0x{{[0-9a-z]+}} <{{.*}}> line:3:8 struct MyBuffer definition +// CHECK:FieldDecl 0x{{[0-9a-z]+}} <line:4:3, col:19> col:19 val 'uint8_t4_packed' diff --git a/clang/test/SemaHLSL/BuiltIns/packed-types.hlsl b/clang/test/SemaHLSL/BuiltIns/packed-types.hlsl new file mode 100644 index 0000000000000..9bfecc5c8c17c --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/packed-types.hlsl @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -finclude-default-header -fsyntax-only -verify -triple dxil-unknown-shadermodel6.6-library %s + +typedef float int8_t4_packed; // expected-error {{cannot combine with previous 'float' declaration specifier}} expected-warning {{typedef requires a name}} +typedef float uint8_t4_packed; // expected-error {{cannot combine with previous 'float' declaration specifier}} expected-warning {{typedef requires a name}} + +void f(int8_t4_packed s_arg, uint8_t4_packed u_arg) { + int8_t4_packed s1; + int8_t4_packed s2[10]; + uint8_t4_packed u1; + uint8_t4_packed u2[10]; + + uint32_t b = s_arg; + uint32_t d = u_arg; + int a = s_arg; + int c = u_arg; + int8_t4_packed u_to_s = u_arg; + uint8_t4_packed s_to_u = s_arg; + float f1 = s_arg; + float f2 = u_arg; +} diff --git a/clang/test/SemaHLSL/Types/int8_t4_packed-size.hlsl b/clang/test/SemaHLSL/Types/int8_t4_packed-size.hlsl new file mode 100644 index 0000000000000..9dcc5411394fd --- /dev/null +++ b/clang/test/SemaHLSL/Types/int8_t4_packed-size.hlsl @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -verify -fnative-half-type -fnative-int16-type %s +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -verify -fnative-half-type -fnative-int16-type %s + +// expected-no-diagnostics +_Static_assert(sizeof(int8_t4_packed) == 4, "int8_t4_packed is 4 bytes"); diff --git a/clang/test/SemaHLSL/Types/uint8_t4_packed-size.hlsl b/clang/test/SemaHLSL/Types/uint8_t4_packed-size.hlsl new file mode 100644 index 0000000000000..fe18cc72f1110 --- /dev/null +++ b/clang/test/SemaHLSL/Types/uint8_t4_packed-size.hlsl @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -verify -fnative-half-type -fnative-int16-type %s +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -verify -fnative-half-type -fnative-int16-type %s + +// expected-no-diagnostics +_Static_assert(sizeof(uint8_t4_packed) == 4, "uint8_t4_packed is 4 bytes"); diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 39e9e89b1ff00..0fe36e8878dda 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1597,6 +1597,8 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { #include "clang/Basic/AMDGPUTypes.def" #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/HLSLIntangibleTypes.def" +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" #define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/SPIRVTypes.def" #define BUILTIN_TYPE(Id, SingletonId) >From 7feaf88c7c40c5de863880871ef2766badcc830e Mon Sep 17 00:00:00 2001 From: Alexander Johnston <[email protected]> Date: Thu, 17 Sep 2026 12:37:13 +0100 Subject: [PATCH 2/3] [HLSL] Add pack_ intrinsics. Adds the pack_u8/s8 and pack_clamp_u8/s8 operations for DirectX and SPIRV. --- clang/include/clang/Basic/Builtins.td | 24 ++++++ clang/include/clang/Basic/HLSLIntrinsics.td | 36 +++++++++ clang/lib/CodeGen/CGHLSLBuiltins.cpp | 24 ++++++ clang/lib/CodeGen/CGHLSLRuntime.h | 4 + clang/lib/Sema/SemaHLSL.cpp | 73 +++++++++++++++++++ .../CodeGenHLSL/builtins/pack_clamp_s8.hlsl | 16 ++++ .../CodeGenHLSL/builtins/pack_clamp_u8.hlsl | 16 ++++ clang/test/CodeGenHLSL/builtins/pack_s8.hlsl | 16 ++++ clang/test/CodeGenHLSL/builtins/pack_u8.hlsl | 16 ++++ .../test/SemaHLSL/BuiltIns/pack_clamp_s8.hlsl | 61 ++++++++++++++++ .../test/SemaHLSL/BuiltIns/pack_clamp_u8.hlsl | 61 ++++++++++++++++ clang/test/SemaHLSL/BuiltIns/pack_s8.hlsl | 61 ++++++++++++++++ clang/test/SemaHLSL/BuiltIns/pack_u8.hlsl | 61 ++++++++++++++++ llvm/include/llvm/IR/IntrinsicsDirectX.td | 6 ++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 4 + llvm/lib/Target/DirectX/DXIL.td | 9 +++ llvm/lib/Target/DirectX/DXILOpLowering.cpp | 34 +++++++++ .../Target/SPIRV/SPIRVInstructionSelector.cpp | 55 ++++++++++++++ llvm/test/CodeGen/DirectX/pack_clamp_s8.ll | 26 +++++++ llvm/test/CodeGen/DirectX/pack_clamp_u8.ll | 26 +++++++ llvm/test/CodeGen/DirectX/pack_s8.ll | 26 +++++++ llvm/test/CodeGen/DirectX/pack_u8.ll | 26 +++++++ .../SPIRV/hlsl-intrinsics/pack_clamp_s8.ll | 44 +++++++++++ .../SPIRV/hlsl-intrinsics/pack_clamp_u8.ll | 42 +++++++++++ .../CodeGen/SPIRV/hlsl-intrinsics/pack_s8.ll | 28 +++++++ .../CodeGen/SPIRV/hlsl-intrinsics/pack_u8.ll | 28 +++++++ 26 files changed, 823 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/pack_clamp_s8.hlsl create mode 100644 clang/test/CodeGenHLSL/builtins/pack_clamp_u8.hlsl create mode 100644 clang/test/CodeGenHLSL/builtins/pack_s8.hlsl create mode 100644 clang/test/CodeGenHLSL/builtins/pack_u8.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/pack_clamp_s8.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/pack_clamp_u8.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/pack_s8.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/pack_u8.hlsl create mode 100644 llvm/test/CodeGen/DirectX/pack_clamp_s8.ll create mode 100644 llvm/test/CodeGen/DirectX/pack_clamp_u8.ll create mode 100644 llvm/test/CodeGen/DirectX/pack_s8.ll create mode 100644 llvm/test/CodeGen/DirectX/pack_u8.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_s8.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_u8.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_s8.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_u8.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 90340ad7f812c..d5d8ffd79659f 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -5878,6 +5878,30 @@ def HLSLDdyFine : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLPackU8 : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_pack_u8"]; + let Attributes = [NoThrow, CustomTypeChecking]; + let Prototype = "void(...)"; +} + +def HLSLPackS8 : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_pack_s8"]; + let Attributes = [NoThrow, CustomTypeChecking]; + let Prototype = "void(...)"; +} + +def HLSLPackClampU8 : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_pack_clamp_u8"]; + let Attributes = [NoThrow, CustomTypeChecking]; + let Prototype = "void(...)"; +} + +def HLSLPackClampS8 : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_pack_clamp_s8"]; + let Attributes = [NoThrow, CustomTypeChecking]; + let Prototype = "void(...)"; +} + // Builtins for XRay. def XRayCustomEvent : Builtin { let Spellings = ["__xray_customevent"]; diff --git a/clang/include/clang/Basic/HLSLIntrinsics.td b/clang/include/clang/Basic/HLSLIntrinsics.td index 163a51dd9497e..6a61d15773675 100644 --- a/clang/include/clang/Basic/HLSLIntrinsics.td +++ b/clang/include/clang/Basic/HLSLIntrinsics.td @@ -1924,3 +1924,39 @@ the specified wave. let Availability = SM6_0; let VaryingMatDims = []; } + +def hlsl_pack_u8 : HLSLOneArgBuiltin<"pack_u8", "__builtin_hlsl_pack_u8"> { + let VaryingTypes = [UInt16Ty, UIntTy]; + let VaryingScalar = 0; + let VaryingVecSizes = [4]; + let VaryingMatDims = []; + let ReturnType = UInt8PackedTy; + let Availability = SM6_6; +} + +def hlsl_pack_s8 : HLSLOneArgBuiltin<"pack_s8", "__builtin_hlsl_pack_s8"> { + let VaryingTypes = [Int16Ty, IntTy]; + let VaryingScalar = 0; + let VaryingVecSizes = [4]; + let VaryingMatDims = []; + let ReturnType = Int8PackedTy; + let Availability = SM6_6; +} + +def hlsl_pack_clamp_u8 : HLSLOneArgBuiltin<"pack_clamp_u8", "__builtin_hlsl_pack_clamp_u8"> { + let VaryingTypes = [Int16Ty, IntTy]; + let VaryingScalar = 0; + let VaryingVecSizes = [4]; + let VaryingMatDims = []; + let ReturnType = UInt8PackedTy; + let Availability = SM6_6; +} + +def hlsl_pack_clamp_s8 : HLSLOneArgBuiltin<"pack_clamp_s8", "__builtin_hlsl_pack_clamp_s8"> { + let VaryingTypes = [Int16Ty, IntTy]; + let VaryingScalar = 0; + let VaryingVecSizes = [4]; + let VaryingMatDims = []; + let ReturnType = Int8PackedTy; + let Availability = SM6_6; +} diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index b1ec72ae46242..014373b7d2563 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -1705,6 +1705,30 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, ArrayRef<Value *>{Op0}, nullptr, "hlsl.ddy.fine"); } + case Builtin::BI__builtin_hlsl_pack_u8: { + Value *Op0 = EmitScalarExpr(E->getArg(0)); + Intrinsic::ID ID = CGM.getHLSLRuntime().getPackU8Intrinsic(); + return Builder.CreateIntrinsic(/*ReturnType=*/Builder.getInt32Ty(), ID, + {Op0}, nullptr, "hlsl.pack.u8"); + } + case Builtin::BI__builtin_hlsl_pack_s8: { + Value *Op0 = EmitScalarExpr(E->getArg(0)); + Intrinsic::ID ID = CGM.getHLSLRuntime().getPackS8Intrinsic(); + return Builder.CreateIntrinsic(/*ReturnType=*/Builder.getInt32Ty(), ID, + {Op0}, nullptr, "hlsl.pack.s8"); + } + case Builtin::BI__builtin_hlsl_pack_clamp_u8: { + Value *Op0 = EmitScalarExpr(E->getArg(0)); + Intrinsic::ID ID = CGM.getHLSLRuntime().getPackClampU8Intrinsic(); + return Builder.CreateIntrinsic(/*ReturnType=*/Builder.getInt32Ty(), ID, + {Op0}, nullptr, "hlsl.pack.clamp.u8"); + } + case Builtin::BI__builtin_hlsl_pack_clamp_s8: { + Value *Op0 = EmitScalarExpr(E->getArg(0)); + Intrinsic::ID ID = CGM.getHLSLRuntime().getPackClampS8Intrinsic(); + return Builder.CreateIntrinsic(/*ReturnType=*/Builder.getInt32Ty(), ID, + {Op0}, nullptr, "hlsl.pack.clamp.s8"); + } case Builtin::BI__builtin_get_spirv_spec_constant_bool: case Builtin::BI__builtin_get_spirv_spec_constant_short: case Builtin::BI__builtin_get_spirv_spec_constant_ushort: diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index f551bb006ea2c..0600f368ca4d8 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -211,6 +211,10 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(DdyCoarse, ddy_coarse) GENERATE_HLSL_INTRINSIC_FUNCTION(DdxFine, ddx_fine) GENERATE_HLSL_INTRINSIC_FUNCTION(DdyFine, ddy_fine) + GENERATE_HLSL_INTRINSIC_FUNCTION(PackS8, pack_s8) + GENERATE_HLSL_INTRINSIC_FUNCTION(PackU8, pack_u8) + GENERATE_HLSL_INTRINSIC_FUNCTION(PackClampS8, pack_clamp_s8) + GENERATE_HLSL_INTRINSIC_FUNCTION(PackClampU8, pack_clamp_u8) //===----------------------------------------------------------------------===// // End of reserved area for HLSL intrinsic getters. diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index f0e71297cf4b2..6f6f420e67cbc 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -4860,6 +4860,79 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { getASTContext().UnsignedIntTy); break; } + case Builtin::BI__builtin_hlsl_pack_u8: { + if (SemaRef.checkArgCount(TheCall, 1)) + return true; + const auto *VecTy = TheCall->getArg(0)->getType()->getAs<VectorType>(); + if (!VecTy) { + SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_builtin_invalid_arg_type) + << 1 << /* vector of */ 4 << /* unsigned integer */ 3 << /* no fp */ 0 + << TheCall->getArg(0)->getType(); + return true; + } + QualType ElementTy = VecTy->getElementType(); + if (!ElementTy->isUnsignedIntegerType() || + SemaRef.Context.getTypeSize(ElementTy) == 64 || + VecTy->getNumElements() != 4) { + SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_builtin_invalid_arg_type) + << 1 << /* vector of */ 4 << /* unsigned integer */ 3 << /* no fp */ 0 + << TheCall->getArg(0)->getType(); + return true; + } + TheCall->setType(getASTContext().UInt8_4PackedTy); + break; + } + case Builtin::BI__builtin_hlsl_pack_clamp_u8: { + if (SemaRef.checkArgCount(TheCall, 1)) + return true; + const auto *VecTy = TheCall->getArg(0)->getType()->getAs<VectorType>(); + if (!VecTy) { + SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_builtin_invalid_arg_type) + << 1 << /* vector of */ 4 << /* signed integer */ 2 << /* no fp */ 0 + << TheCall->getArg(0)->getType(); + return true; + } + QualType ElementTy = VecTy->getElementType(); + if (!ElementTy->isSignedIntegerType() || + SemaRef.Context.getTypeSize(ElementTy) == 64 || + VecTy->getNumElements() != 4) { + SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_builtin_invalid_arg_type) + << 1 << /* vector of */ 4 << /* signed integer */ 2 << /* no fp */ 0 + << TheCall->getArg(0)->getType(); + return true; + } + TheCall->setType(getASTContext().UInt8_4PackedTy); + break; + } + case Builtin::BI__builtin_hlsl_pack_s8: + case Builtin::BI__builtin_hlsl_pack_clamp_s8: { + if (SemaRef.checkArgCount(TheCall, 1)) + return true; + const auto *VecTy = TheCall->getArg(0)->getType()->getAs<VectorType>(); + if (!VecTy) { + SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_builtin_invalid_arg_type) + << 1 << /* vector of */ 4 << /* signed integer */ 2 << /* no fp */ 0 + << TheCall->getArg(0)->getType(); + return true; + } + QualType ElementTy = VecTy->getElementType(); + if (!ElementTy->isSignedIntegerType() || + SemaRef.Context.getTypeSize(ElementTy) == 64 || + VecTy->getNumElements() != 4) { + SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_builtin_invalid_arg_type) + << 1 << /* vector of */ 4 << /* signed integer */ 2 << /* no fp */ 0 + << TheCall->getArg(0)->getType(); + return true; + } + TheCall->setType(getASTContext().Int8_4PackedTy); + break; + } } return false; } diff --git a/clang/test/CodeGenHLSL/builtins/pack_clamp_s8.hlsl b/clang/test/CodeGenHLSL/builtins/pack_clamp_s8.hlsl new file mode 100644 index 0000000000000..80db19d467f10 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/pack_clamp_s8.hlsl @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.6-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \ +// RUN: FileCheck %s -DCALL=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \ +// RUN: FileCheck %s -DCALL=spv + +// CHECK-LABEL: define {{.*}} i32 @_Z8test_u16Dv4_s +// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.clamp.s8.v4i16(<4 x i16> %{{.*}}) +// CHECK-NEXT: ret i32 [[VAR]] +int8_t4_packed test_u16(int16_t4 val) { return pack_clamp_s8(val); } + +// CHECK-LABEL: define {{.*}} i32 @_Z8test_u32Dv4_i +// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.clamp.s8.v4i32(<4 x i32> %{{.*}}) +// CHECK-NEXT: ret i32 [[VAR]] +int8_t4_packed test_u32(int4 val) { return pack_clamp_s8(val); } diff --git a/clang/test/CodeGenHLSL/builtins/pack_clamp_u8.hlsl b/clang/test/CodeGenHLSL/builtins/pack_clamp_u8.hlsl new file mode 100644 index 0000000000000..99beb20843ea8 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/pack_clamp_u8.hlsl @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.6-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \ +// RUN: FileCheck %s -DCALL=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \ +// RUN: FileCheck %s -DCALL=spv + +// CHECK-LABEL: define {{.*}} i32 @_Z8test_u16Dv4_s +// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.clamp.u8.v4i16(<4 x i16> %{{.*}}) +// CHECK-NEXT: ret i32 [[VAR]] +uint8_t4_packed test_u16(int16_t4 val) { return pack_clamp_u8(val); } + +// CHECK-LABEL: define {{.*}} i32 @_Z8test_u32Dv4_i +// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.clamp.u8.v4i32(<4 x i32> %{{.*}}) +// CHECK-NEXT: ret i32 [[VAR]] +uint8_t4_packed test_u32(int4 val) { return pack_clamp_u8(val); } diff --git a/clang/test/CodeGenHLSL/builtins/pack_s8.hlsl b/clang/test/CodeGenHLSL/builtins/pack_s8.hlsl new file mode 100644 index 0000000000000..4b90a2890a54b --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/pack_s8.hlsl @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.6-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \ +// RUN: FileCheck %s -DCALL=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \ +// RUN: FileCheck %s -DCALL=spv + +// CHECK-LABEL: define {{.*}} i32 @_Z8test_s16Dv4_s +// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.s8.v4i16(<4 x i16> %{{.*}}) +// CHECK-NEXT: ret i32 [[VAR]] +int8_t4_packed test_s16(int16_t4 val) { return pack_s8(val); } + +// CHECK-LABEL: define {{.*}} i32 @_Z8test_s32Dv4_i +// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.s8.v4i32(<4 x i32> %{{.*}}) +// CHECK-NEXT: ret i32 [[VAR]] +int8_t4_packed test_s32(int4 val) { return pack_s8(val); } diff --git a/clang/test/CodeGenHLSL/builtins/pack_u8.hlsl b/clang/test/CodeGenHLSL/builtins/pack_u8.hlsl new file mode 100644 index 0000000000000..b4ea9e78b12b4 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/pack_u8.hlsl @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.6-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \ +// RUN: FileCheck %s -DCALL=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-library %s \ +// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \ +// RUN: FileCheck %s -DCALL=spv + +// CHECK-LABEL: define {{.*}} i32 @_Z8test_u16Dv4_t +// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.u8.v4i16(<4 x i16> %{{.*}}) +// CHECK-NEXT: ret i32 [[VAR]] +uint8_t4_packed test_u16(uint16_t4 val) { return pack_u8(val); } + +// CHECK-LABEL: define {{.*}} i32 @_Z8test_u32Dv4_j +// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.u8.v4i32(<4 x i32> %{{.*}}) +// CHECK-NEXT: ret i32 [[VAR]] +uint8_t4_packed test_u32(uint4 val) { return pack_u8(val); } diff --git a/clang/test/SemaHLSL/BuiltIns/pack_clamp_s8.hlsl b/clang/test/SemaHLSL/BuiltIns/pack_clamp_s8.hlsl new file mode 100644 index 0000000000000..2a87693b47fbf --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/pack_clamp_s8.hlsl @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -emit-llvm-only -disable-llvm-passes -verify + +void test_no_args() { + pack_clamp_s8(); + // expected-error@-1 {{no matching function for call to 'pack_clamp_s8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 0 were provided}} +} + +int8_t4_packed test_extra_args(int32_t4 p0) { + return pack_clamp_s8(p0, p0); + // expected-error@-1 {{no matching function for call to 'pack_clamp_s8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 2 were provided}} +} + +int8_t4_packed test_64bit_arg(int64_t4 p0) { + return pack_clamp_s8(p0); + // expected-error@-1 {{call to 'pack_clamp_s8' is ambiguous}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}} +} + +int8_t4_packed test_float_vec_arg(float32_t4 p0) { + return pack_clamp_s8(p0); + // expected-error@-1 {{call to 'pack_clamp_s8' is ambiguous}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}} +} + +int8_t4_packed test_wrong_vec_elems(int32_t3 p0) { + return pack_clamp_s8(p0); + // expected-error@-1 {{no matching function for call to 'pack_clamp_s8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: no known conversion from}} +} + +void test_builtin_no_args() { + __builtin_hlsl_pack_clamp_s8(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} +} + +int8_t4_packed test_builtin_extra_args(int32_t4 p0) { + return __builtin_hlsl_pack_clamp_s8(p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} +} + +int8_t4_packed test_builtin_64bit_arg(int64_t4 p0) { + return __builtin_hlsl_pack_clamp_s8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'int64_t4' (aka 'vector<int64_t, 4>'))}} +} + +int8_t4_packed test_builtin_float_vec_arg(float32_t4 p0) { + return __builtin_hlsl_pack_clamp_s8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'float32_t4' (aka 'vector<float32_t, 4>'))}} +} + +int8_t4_packed test_builtin_wrong_vec_elems(int32_t3 p0) { + return __builtin_hlsl_pack_clamp_s8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'int32_t3' (aka 'vector<int32_t, 3>'))}} +} + +int8_t4_packed test_builtin_scalar_arg(int p0) { + return __builtin_hlsl_pack_clamp_s8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'int')}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/pack_clamp_u8.hlsl b/clang/test/SemaHLSL/BuiltIns/pack_clamp_u8.hlsl new file mode 100644 index 0000000000000..f4f1c50943916 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/pack_clamp_u8.hlsl @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -emit-llvm-only -disable-llvm-passes -verify + +void test_no_args() { + pack_clamp_u8(); + // expected-error@-1 {{no matching function for call to 'pack_clamp_u8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 0 were provided}} +} + +uint8_t4_packed test_extra_args(int32_t4 p0) { + return pack_clamp_u8(p0, p0); + // expected-error@-1 {{no matching function for call to 'pack_clamp_u8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 2 were provided}} +} + +uint8_t4_packed test_64bit_arg(int64_t4 p0) { + return pack_clamp_u8(p0); + // expected-error@-1 {{call to 'pack_clamp_u8' is ambiguous}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}} +} + +uint8_t4_packed test_float_vec_arg(float32_t4 p0) { + return pack_clamp_u8(p0); + // expected-error@-1 {{call to 'pack_clamp_u8' is ambiguous}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}} +} + +uint8_t4_packed test_wrong_vec_elems(int32_t3 p0) { + return pack_clamp_u8(p0); + // expected-error@-1 {{no matching function for call to 'pack_clamp_u8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: no known conversion from}} +} + +void test_builtin_no_args() { + __builtin_hlsl_pack_clamp_u8(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} +} + +uint8_t4_packed test_builtin_extra_args(int32_t4 p0) { + return __builtin_hlsl_pack_clamp_u8(p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} +} + +uint8_t4_packed test_builtin_64bit_arg(int64_t4 p0) { + return __builtin_hlsl_pack_clamp_u8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'int64_t4' (aka 'vector<int64_t, 4>'))}} +} + +uint8_t4_packed test_builtin_float_vec_arg(float32_t4 p0) { + return __builtin_hlsl_pack_clamp_u8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'float32_t4' (aka 'vector<float32_t, 4>'))}} +} + +uint8_t4_packed test_builtin_wrong_vec_elems(int32_t3 p0) { + return __builtin_hlsl_pack_clamp_u8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'int32_t3' (aka 'vector<int32_t, 3>'))}} +} + +uint8_t4_packed test_builtin_scalar_arg(int p0) { + return __builtin_hlsl_pack_clamp_u8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'int')}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/pack_s8.hlsl b/clang/test/SemaHLSL/BuiltIns/pack_s8.hlsl new file mode 100644 index 0000000000000..6d9bcc615ef1f --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/pack_s8.hlsl @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -emit-llvm-only -disable-llvm-passes -verify + +void test_no_args() { + pack_s8(); + // expected-error@-1 {{no matching function for call to 'pack_s8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 0 were provided}} +} + +int8_t4_packed test_extra_args(int32_t4 p0) { + return pack_s8(p0, p0); + // expected-error@-1 {{no matching function for call to 'pack_s8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 2 were provided}} +} + +int8_t4_packed test_64bit_arg(int64_t4 p0) { + return pack_s8(p0); + // expected-error@-1 {{call to 'pack_s8' is ambiguous}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}} +} + +int8_t4_packed test_float_vec_arg(float32_t4 p0) { + return pack_s8(p0); + // expected-error@-1 {{call to 'pack_s8' is ambiguous}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}} +} + +int8_t4_packed test_wrong_vec_elems(int32_t3 p0) { + return pack_s8(p0); + // expected-error@-1 {{no matching function for call to 'pack_s8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: no known conversion from}} +} + +void test_builtin_no_args() { + __builtin_hlsl_pack_s8(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} +} + +int8_t4_packed test_builtin_extra_args(int32_t4 p0) { + return __builtin_hlsl_pack_s8(p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} +} + +int8_t4_packed test_builtin_64bit_arg(int64_t4 p0) { + return __builtin_hlsl_pack_s8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'int64_t4' (aka 'vector<int64_t, 4>'))}} +} + +int8_t4_packed test_builtin_float_vec_arg(float32_t4 p0) { + return __builtin_hlsl_pack_s8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'float32_t4' (aka 'vector<float32_t, 4>'))}} +} + +int8_t4_packed test_builtin_wrong_vec_elems(int32_t3 p0) { + return __builtin_hlsl_pack_s8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'int32_t3' (aka 'vector<int32_t, 3>'))}} +} + +int8_t4_packed test_builtin_scalar_arg(int p0) { + return __builtin_hlsl_pack_s8(p0); + // expected-error@-1 {{1st argument must be a vector of signed integer types (was 'int')}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/pack_u8.hlsl b/clang/test/SemaHLSL/BuiltIns/pack_u8.hlsl new file mode 100644 index 0000000000000..8fdc95bbed03c --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/pack_u8.hlsl @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -emit-llvm-only -disable-llvm-passes -verify + +void test_no_args() { + pack_u8(); + // expected-error@-1 {{no matching function for call to 'pack_u8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 0 were provided}} +} + +uint8_t4_packed test_extra_args(uint32_t4 p0) { + return pack_u8(p0, p0); + // expected-error@-1 {{no matching function for call to 'pack_u8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 2 were provided}} +} + +uint8_t4_packed test_64bit_arg(uint64_t4 p0) { + return pack_u8(p0); + // expected-error@-1 {{call to 'pack_u8' is ambiguous}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}} +} + +uint8_t4_packed test_float_vec_arg(float32_t4 p0) { + return pack_u8(p0); + // expected-error@-1 {{call to 'pack_u8' is ambiguous}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}} +} + +uint8_t4_packed test_wrong_vec_elems(uint32_t3 p0) { + return pack_u8(p0); + // expected-error@-1 {{no matching function for call to 'pack_u8'}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: no known conversion from}} +} + +void test_builtin_no_args() { + __builtin_hlsl_pack_u8(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} +} + +uint8_t4_packed test_builtin_extra_args(uint32_t4 p0) { + return __builtin_hlsl_pack_u8(p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} +} + +uint8_t4_packed test_builtin_64bit_arg(uint64_t4 p0) { + return __builtin_hlsl_pack_u8(p0); + // expected-error@-1 {{1st argument must be a vector of unsigned integer types (was 'uint64_t4' (aka 'vector<uint64_t, 4>'))}} +} + +uint8_t4_packed test_builtin_float_vec_arg(float32_t4 p0) { + return __builtin_hlsl_pack_u8(p0); + // expected-error@-1 {{1st argument must be a vector of unsigned integer types (was 'float32_t4' (aka 'vector<float32_t, 4>'))}} +} + +uint8_t4_packed test_builtin_wrong_vec_elems(uint32_t3 p0) { + return __builtin_hlsl_pack_u8(p0); + // expected-error@-1 {{1st argument must be a vector of unsigned integer types (was 'uint32_t3' (aka 'vector<uint32_t, 3>'))}} +} + +uint8_t4_packed test_builtin_scalar_arg(uint p0) { + return __builtin_hlsl_pack_u8(p0); + // expected-error@-1 {{1st argument must be a vector of unsigned integer types (was 'uint' (aka 'unsigned int'))}} +} diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index f90340c379386..0ab61b789c226 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -346,4 +346,10 @@ def int_dx_store_output [llvm_i32_ty /*SigElementId*/, llvm_i32_ty /*RowIndex*/, llvm_i8_ty /*ColIndex*/, llvm_any_ty /*Value*/], [IntrConvergent]>; + +def int_dx_pack_u8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>; +def int_dx_pack_s8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>; +def int_dx_pack_clamp_u8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>; +def int_dx_pack_clamp_s8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>; + } diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index 86b49a8ee446a..7d4fac1226846 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -365,5 +365,9 @@ def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty] def int_spv_unpackhalf2x16 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [llvm_i32_ty], [IntrNoMem]>; def int_spv_packhalf2x16 : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty], [IntrNoMem]>; + def int_spv_pack_u8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>; + def int_spv_pack_s8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>; + def int_spv_pack_clamp_u8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>; + def int_spv_pack_clamp_s8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>; } diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index 4beafd0c619b0..2a18b7ee074be 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -1539,3 +1539,12 @@ def CreateHandleFromHeap : DXILOp<218, createHandleFromHeap> { let stages = [Stages<DXIL1_6, [all_stages]>]; let attributes = [Attributes<DXIL1_0, [ReadNone]>]; } + +def Pack4x8 : DXILOp<220, pack4x8> { + let Doc = "pack 4 integer values into a single 32 bit value"; + let arguments = [Int8Ty, OverloadTy, OverloadTy, OverloadTy, OverloadTy]; + let overloads = [Overloads<DXIL1_6, [Int16Ty, Int32Ty]>]; + let result = Int32Ty; + let stages = [Stages<DXIL1_6, [all_stages]>]; + let attributes = [Attributes<DXIL1_6, [ReadNone]>]; +} diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index aa73629eee232..41a126b5749c0 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -1319,6 +1319,30 @@ class OpLowerer { }); } + [[nodiscard]] bool lowerPack(Function &F, uint32_t PackOpCode) { + IRBuilder<> &IRB = OpBuilder.getIRB(); + Type *RetTy = IRB.getInt32Ty(); + return replaceFunction(F, [&](CallInst *CI) -> Error { + IRB.SetInsertPoint(CI); + SmallVector<Value *, 5> Args; + Args.push_back(IRB.getInt8(PackOpCode)); + + // Disassemble the vector to fill args 1-5 of the pack op. + Value *VecArg = CI->getArgOperand(0); + for (int i = 1; i < 5; i++) + Args.push_back(IRB.CreateExtractElement(VecArg, i - 1)); + + Expected<CallInst *> OpCall = + OpBuilder.tryCreateOp(OpCode::Pack4x8, Args, CI->getName(), RetTy); + if (Error E = OpCall.takeError()) + return E; + + CI->replaceAllUsesWith(*OpCall); + CI->eraseFromParent(); + return Error::success(); + }); + } + bool lowerIntrinsics() { bool Updated = false; bool HasErrors = false; @@ -1439,6 +1463,16 @@ class OpLowerer { case Intrinsic::is_fpclass: HasErrors |= lowerIsFPClass(F); break; + case Intrinsic::dx_pack_u8: + case Intrinsic::dx_pack_s8: + HasErrors |= lowerPack(F, 0); + break; + case Intrinsic::dx_pack_clamp_u8: + HasErrors |= lowerPack(F, 1); + break; + case Intrinsic::dx_pack_clamp_s8: + HasErrors |= lowerPack(F, 2); + break; } Updated = true; } diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 1d821c5aec993..c85f9016394f9 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -485,6 +485,8 @@ class SPIRVInstructionSelector : public InstructionSelector { MachineInstr &I) const; bool selectDerivativeInst(Register ResVReg, SPIRVTypeInst ResType, MachineInstr &I, const unsigned DPdOpCode) const; + bool selectPackInst(Register ResVReg, SPIRVTypeInst ResType, MachineInstr &I, + const bool Signed, const bool Clamp) const; // Utilities Register buildI32Constant(uint32_t Val, MachineInstr &I, SPIRVTypeInst ResType = nullptr) const; @@ -5254,6 +5256,51 @@ bool SPIRVInstructionSelector::selectDerivativeInst( return true; } +bool SPIRVInstructionSelector::selectPackInst(Register ResVReg, + SPIRVTypeInst ResType, + MachineInstr &I, + const bool Signed, + const bool Clamp) const { + MachineIRBuilder MIRBuilder(I); + Register SrcReg = I.getOperand(2).getReg(); + SPIRVTypeInst SrcType = GR.getSPIRVTypeForVReg(SrcReg); + + // pack_clamp_ instructions require SClamp before performing SConvert + // limits are determined by if the pack_clamp is signed or not + if (Clamp) { + const unsigned ElemWidth = GR.getScalarOrVectorBitWidth(SrcType); + APInt Lower = + Signed ? APInt(ElemWidth, -128, true) : APInt::getZero(ElemWidth); + APInt Upper = + Signed ? APInt(ElemWidth, 127, true) : APInt(ElemWidth, 255, true); + bool ZeroAsNull = !STI.isShader(); + Register LowerLimit = + GR.getOrCreateConstVector(Lower, I, SrcType, TII, ZeroAsNull); + Register UpperLimit = + GR.getOrCreateConstVector(Upper, I, SrcType, TII, ZeroAsNull); + + Register ClampedReg = MRI->createVirtualRegister(GR.getRegClass(SrcType)); + // Regardless of if we are using pack_clamp_u8 or pack_clamp_s8 we want to + // generate a signed clamp + if (!selectExtInst(ClampedReg, SrcType, I, CL::s_clamp, GL::SClamp, + /*setMIFlags=*/true, /*useMISrc=*/false, + {SrcReg, LowerLimit, UpperLimit})) + return false; + SrcReg = ClampedReg; + } + + // Narrow to an i8 vector, then bitcast. Convert sign doesn't matter here + SPIRVTypeInst I8Type = GR.getOrCreateSPIRVIntegerType(8, MIRBuilder); + SPIRVTypeInst I8x4Type = + GR.getOrCreateSPIRVVectorType(I8Type, 4, MIRBuilder, true); + Register I8x4Reg = MRI->createVirtualRegister(GR.getRegClass(I8x4Type)); + auto ConvertOpcode = Signed ? SPIRV::OpSConvert : SPIRV::OpUConvert; + if (!selectOpWithSrcs(I8x4Reg, I8x4Type, I, {SrcReg}, ConvertOpcode)) + return false; + + return selectOpWithSrcs(ResVReg, ResType, I, {I8x4Reg}, SPIRV::OpBitcast); +} + bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, SPIRVTypeInst ResType, MachineInstr &I) const { @@ -5842,6 +5889,14 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, MIB.constrainAllUses(TII, TRI, RBI); return true; } + case Intrinsic::spv_pack_u8: + case Intrinsic::spv_pack_s8: + // For non-clamp packs the sign is meaningless + return selectPackInst(ResVReg, ResType, I, false, false); + case Intrinsic::spv_pack_clamp_u8: + return selectPackInst(ResVReg, ResType, I, false, true); + case Intrinsic::spv_pack_clamp_s8: + return selectPackInst(ResVReg, ResType, I, true, true); default: return diagnoseUnsupported(I, "intrinsic selection not implemented."); } diff --git a/llvm/test/CodeGen/DirectX/pack_clamp_s8.ll b/llvm/test/CodeGen/DirectX/pack_clamp_s8.ll new file mode 100644 index 0000000000000..e8c9e5b4d2425 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/pack_clamp_s8.ll @@ -0,0 +1,26 @@ +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.6-library %s | FileCheck %s + +define noundef i32 @pack_clamp_s8_16(<4 x i16> noundef %a) { +; CHECK: [[one:%.*]] = extractelement <4 x i16> %a, i64 0 +; CHECK: [[two:%.*]] = extractelement <4 x i16> %a, i64 1 +; CHECK: [[three:%.*]] = extractelement <4 x i16> %a, i64 2 +; CHECK: [[four:%.*]] = extractelement <4 x i16> %a, i64 3 +; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i16(i32 220, i8 2, i16 [[one]], i16 [[two]], i16 [[three]], i16 [[four]]) +; ret i32 [[packed]] + %packed = call i32 @llvm.dx.pack.clamp.s8.v4i16(<4 x i16> %a) + ret i32 %packed +} + +define noundef i32 @pack_clamp_s8_32(<4 x i32> noundef %a) { +; CHECK: [[one:%.*]] = extractelement <4 x i32> %a, i64 0 +; CHECK: [[two:%.*]] = extractelement <4 x i32> %a, i64 1 +; CHECK: [[three:%.*]] = extractelement <4 x i32> %a, i64 2 +; CHECK: [[four:%.*]] = extractelement <4 x i32> %a, i64 3 +; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i32(i32 220, i8 2, i32 [[one]], i32 [[two]], i32 [[three]], i32 [[four]]) +; ret i32 [[packed]] + %packed = call i32 @llvm.dx.pack.clamp.s8.v4i32(<4 x i32> %a) + ret i32 %packed +} + +declare i32 @llvm.dx.pack.clamp.s8.v4i16(<4 x i16>) +declare i32 @llvm.dx.pack.clamp.s8.v4i32(<4 x i32>) diff --git a/llvm/test/CodeGen/DirectX/pack_clamp_u8.ll b/llvm/test/CodeGen/DirectX/pack_clamp_u8.ll new file mode 100644 index 0000000000000..ec854fff6a02f --- /dev/null +++ b/llvm/test/CodeGen/DirectX/pack_clamp_u8.ll @@ -0,0 +1,26 @@ +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.6-library %s | FileCheck %s + +define noundef i32 @pack_clamp_u8_16(<4 x i16> noundef %a) { +; CHECK: [[one:%.*]] = extractelement <4 x i16> %a, i64 0 +; CHECK: [[two:%.*]] = extractelement <4 x i16> %a, i64 1 +; CHECK: [[three:%.*]] = extractelement <4 x i16> %a, i64 2 +; CHECK: [[four:%.*]] = extractelement <4 x i16> %a, i64 3 +; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i16(i32 220, i8 1, i16 [[one]], i16 [[two]], i16 [[three]], i16 [[four]]) +; ret i32 [[packed]] + %packed = call i32 @llvm.dx.pack.clamp.u8.v4i16(<4 x i16> %a) + ret i32 %packed +} + +define noundef i32 @pack_clamp_u8_32(<4 x i32> noundef %a) { +; CHECK: [[one:%.*]] = extractelement <4 x i32> %a, i64 0 +; CHECK: [[two:%.*]] = extractelement <4 x i32> %a, i64 1 +; CHECK: [[three:%.*]] = extractelement <4 x i32> %a, i64 2 +; CHECK: [[four:%.*]] = extractelement <4 x i32> %a, i64 3 +; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i32(i32 220, i8 1, i32 [[one]], i32 [[two]], i32 [[three]], i32 [[four]]) +; ret i32 [[packed]] + %packed = call i32 @llvm.dx.pack.clamp.u8.v4i32(<4 x i32> %a) + ret i32 %packed +} + +declare i32 @llvm.dx.pack.clamp.u8.v4i16(<4 x i16>) +declare i32 @llvm.dx.pack.clamp.u8.v4i32(<4 x i32>) diff --git a/llvm/test/CodeGen/DirectX/pack_s8.ll b/llvm/test/CodeGen/DirectX/pack_s8.ll new file mode 100644 index 0000000000000..1920147ec3839 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/pack_s8.ll @@ -0,0 +1,26 @@ +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.6-library %s | FileCheck %s + +define noundef i32 @pack_s8_16(<4 x i16> noundef %a) { +; CHECK: [[one:%.*]] = extractelement <4 x i16> %a, i64 0 +; CHECK: [[two:%.*]] = extractelement <4 x i16> %a, i64 1 +; CHECK: [[three:%.*]] = extractelement <4 x i16> %a, i64 2 +; CHECK: [[four:%.*]] = extractelement <4 x i16> %a, i64 3 +; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i16(i32 220, i8 0, i16 [[one]], i16 [[two]], i16 [[three]], i16 [[four]]) +; ret i32 [[packed]] + %packed = call i32 @llvm.dx.pack.s8.v4i16(<4 x i16> %a) + ret i32 %packed +} + +define noundef i32 @pack_s8_32(<4 x i32> noundef %a) { +; CHECK: [[one:%.*]] = extractelement <4 x i32> %a, i64 0 +; CHECK: [[two:%.*]] = extractelement <4 x i32> %a, i64 1 +; CHECK: [[three:%.*]] = extractelement <4 x i32> %a, i64 2 +; CHECK: [[four:%.*]] = extractelement <4 x i32> %a, i64 3 +; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i32(i32 220, i8 0, i32 [[one]], i32 [[two]], i32 [[three]], i32 [[four]]) +; ret i32 [[packed]] + %packed = call i32 @llvm.dx.pack.s8.v4i32(<4 x i32> %a) + ret i32 %packed +} + +declare i32 @llvm.dx.pack.s8.v4i16(<4 x i16>) +declare i32 @llvm.dx.pack.s8.v4i32(<4 x i32>) diff --git a/llvm/test/CodeGen/DirectX/pack_u8.ll b/llvm/test/CodeGen/DirectX/pack_u8.ll new file mode 100644 index 0000000000000..38360f69e2d59 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/pack_u8.ll @@ -0,0 +1,26 @@ +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.6-library %s | FileCheck %s + +define noundef i32 @pack_u8_16(<4 x i16> noundef %a) { +; CHECK: [[one:%.*]] = extractelement <4 x i16> %a, i64 0 +; CHECK: [[two:%.*]] = extractelement <4 x i16> %a, i64 1 +; CHECK: [[three:%.*]] = extractelement <4 x i16> %a, i64 2 +; CHECK: [[four:%.*]] = extractelement <4 x i16> %a, i64 3 +; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i16(i32 220, i8 0, i16 [[one]], i16 [[two]], i16 [[three]], i16 [[four]]) +; ret i32 [[packed]] + %packed = call i32 @llvm.dx.pack.u8.v4i16(<4 x i16> %a) + ret i32 %packed +} + +define noundef i32 @pack_u8_32(<4 x i32> noundef %a) { +; CHECK: [[one:%.*]] = extractelement <4 x i32> %a, i64 0 +; CHECK: [[two:%.*]] = extractelement <4 x i32> %a, i64 1 +; CHECK: [[three:%.*]] = extractelement <4 x i32> %a, i64 2 +; CHECK: [[four:%.*]] = extractelement <4 x i32> %a, i64 3 +; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i32(i32 220, i8 0, i32 [[one]], i32 [[two]], i32 [[three]], i32 [[four]]) +; ret i32 [[packed]] + %packed = call i32 @llvm.dx.pack.u8.v4i32(<4 x i32> %a) + ret i32 %packed +} + +declare i32 @llvm.dx.pack.u8.v4i16(<4 x i16>) +declare i32 @llvm.dx.pack.u8.v4i32(<4 x i32>) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_s8.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_s8.ll new file mode 100644 index 0000000000000..f6784e076265c --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_s8.ll @@ -0,0 +1,44 @@ +; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %} + +; CHECK: [[import:%.*]] = OpExtInstImport "GLSL.std.450" + +; CHECK-DAG: [[int8:%.*]] = OpTypeInt 8 0 +; CHECK-DAG: [[int8x4:%.*]] = OpTypeVector [[int8]] 4 +; CHECK-DAG: [[int16:%.*]] = OpTypeInt 16 0 +; CHECK-DAG: [[int16x4:%.*]] = OpTypeVector [[int16]] 4 +; CHECK-DAG: [[int32:%.*]] = OpTypeInt 32 0 +; CHECK-DAG: [[int32x4:%.*]] = OpTypeVector [[int32]] 4 + +; 65408 is -128 for SClamp +; CHECK-DAG: [[int16_65408:%.*]] = OpConstant [[int16]] 65408 +; CHECK-DAG: [[int16_65408x4:%.*]] = OpConstantComposite [[int16x4]] [[int16_65408]] [[int16_65408]] [[int16_65408]] [[int16_65408]] +; CHECK-DAG: [[int16_127:%.*]] = OpConstant [[int16]] 127 +; CHECK-DAG: [[int16_127x4:%.*]] = OpConstantComposite [[int16x4]] [[int16_127]] [[int16_127]] [[int16_127]] [[int16_127]] + +; 4294967168 is -128 for SClamp +; CHECK-DAG: [[int32_4294967168:%.*]] = OpConstant [[int32]] 4294967168 +; CHECK-DAG: [[int32_4294967168x4:%.*]] = OpConstantComposite [[int32x4]] [[int32_4294967168]] [[int32_4294967168]] [[int32_4294967168]] [[int32_4294967168]] +; CHECK-DAG: [[int32_127:%.*]] = OpConstant [[int32]] 127 +; CHECK-DAG: [[int32_127x4:%.*]] = OpConstantComposite [[int32x4]] [[int32_127]] [[int32_127]] [[int32_127]] [[int32_127]] + +define noundef i32 @pack_clamp_s8_16(<4 x i16> noundef %a) { +; CHECK: [[in:%.*]] = OpFunctionParameter [[int16x4]] +; CHECK: [[clamped:%.*]] = OpExtInst [[int16x4]] [[import]] SClamp [[in]] [[int16_65408x4]] [[int16_127x4]] +; CHECK: [[converted:%.*]] = OpSConvert [[int8x4]] [[clamped]] +; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]] + %packed = call i32 @llvm.spv.pack.clamp.s8.v4i16(<4 x i16> %a) + ret i32 %packed +} + +define noundef i32 @pack_clamp_s8_32(<4 x i32> noundef %a) { +; CHECK: [[in:%.*]] = OpFunctionParameter [[int32x4]] +; CHECK: [[clamped:%.*]] = OpExtInst [[int32x4]] [[import]] SClamp [[in]] [[int32_4294967168x4]] [[int32_127x4]] +; CHECK: [[converted:%.*]] = OpSConvert [[int8x4]] [[clamped]] +; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]] + %packed = call i32 @llvm.spv.pack.clamp.s8.v4i32(<4 x i32> %a) + ret i32 %packed +} + +declare i32 @llvm.spv.pack.clamp.s8.v4i16(<4 x i16>) +declare i32 @llvm.spv.pack.clamp.s8.v4i32(<4 x i32>) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_u8.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_u8.ll new file mode 100644 index 0000000000000..c5234e3283fee --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_u8.ll @@ -0,0 +1,42 @@ +; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %} + +; CHECK: [[import:%.*]] = OpExtInstImport "GLSL.std.450" + +; CHECK-DAG: [[int8:%.*]] = OpTypeInt 8 0 +; CHECK-DAG: [[int8x4:%.*]] = OpTypeVector [[int8]] 4 +; CHECK-DAG: [[int16:%.*]] = OpTypeInt 16 0 +; CHECK-DAG: [[int16x4:%.*]] = OpTypeVector [[int16]] 4 +; CHECK-DAG: [[int32:%.*]] = OpTypeInt 32 0 +; CHECK-DAG: [[int32x4:%.*]] = OpTypeVector [[int32]] 4 + +; CHECK-DAG: [[int16_0:%.*]] = OpConstant [[int16]] 0 +; CHECK-DAG: [[int16_0x4:%.*]] = OpConstantComposite [[int16x4]] [[int16_0]] [[int16_0]] [[int16_0]] [[int16_0]] +; CHECK-DAG: [[int16_255:%.*]] = OpConstant [[int16]] 255 +; CHECK-DAG: [[int16_255x4:%.*]] = OpConstantComposite [[int16x4]] [[int16_255]] [[int16_255]] [[int16_255]] [[int16_255]] + +; CHECK-DAG: [[int32_0:%.*]] = OpConstant [[int32]] 0 +; CHECK-DAG: [[int32_0x4:%.*]] = OpConstantComposite [[int32x4]] [[int32_0]] [[int32_0]] [[int32_0]] [[int32_0]] +; CHECK-DAG: [[int32_255:%.*]] = OpConstant [[int32]] 255 +; CHECK-DAG: [[int32_255x4:%.*]] = OpConstantComposite [[int32x4]] [[int32_255]] [[int32_255]] [[int32_255]] [[int32_255]] + +define noundef i32 @pack_clamp_u8_16(<4 x i16> noundef %a) { +; CHECK: [[in:%.*]] = OpFunctionParameter [[int16x4]] +; CHECK: [[clamped:%.*]] = OpExtInst [[int16x4]] [[import]] SClamp [[in]] [[int16_0x4]] [[int16_255x4]] +; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[clamped]] +; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]] + %packed = call i32 @llvm.spv.pack.clamp.u8.v4i16(<4 x i16> %a) + ret i32 %packed +} + +define noundef i32 @pack_clamp_u8_32(<4 x i32> noundef %a) { +; CHECK: [[in:%.*]] = OpFunctionParameter [[int32x4]] +; CHECK: [[clamped:%.*]] = OpExtInst [[int32x4]] [[import]] SClamp [[in]] [[int32_0x4]] [[int32_255x4]] +; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[clamped]] +; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]] + %packed = call i32 @llvm.spv.pack.clamp.u8.v4i32(<4 x i32> %a) + ret i32 %packed +} + +declare i32 @llvm.spv.pack.clamp.u8.v4i16(<4 x i16>) +declare i32 @llvm.spv.pack.clamp.u8.v4i32(<4 x i32>) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_s8.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_s8.ll new file mode 100644 index 0000000000000..d16cdaac17a31 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_s8.ll @@ -0,0 +1,28 @@ +; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: [[int8:%.*]] = OpTypeInt 8 0 +; CHECK-DAG: [[int8x4:%.*]] = OpTypeVector [[int8]] 4 +; CHECK-DAG: [[int16:%.*]] = OpTypeInt 16 0 +; CHECK-DAG: [[int16x4:%.*]] = OpTypeVector [[int16]] 4 +; CHECK-DAG: [[int32:%.*]] = OpTypeInt 32 0 +; CHECK-DAG: [[int32x4:%.*]] = OpTypeVector [[int32]] 4 + +define noundef i32 @pack_s8_16(<4 x i16> noundef %a) { +; CHECK: [[in:%.*]] = OpFunctionParameter [[int16x4]] +; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[in]] +; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]] + %packed = call i32 @llvm.spv.pack.s8.v4i16(<4 x i16> %a) + ret i32 %packed +} + +define noundef i32 @pack_s8_32(<4 x i32> noundef %a) { +; CHECK: [[in:%.*]] = OpFunctionParameter [[int32x4]] +; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[in]] +; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]] + %packed = call i32 @llvm.spv.pack.s8.v4i32(<4 x i32> %a) + ret i32 %packed +} + +declare i32 @llvm.spv.pack.s8.v4i16(<4 x i16>) +declare i32 @llvm.spv.pack.s8.v4i32(<4 x i32>) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_u8.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_u8.ll new file mode 100644 index 0000000000000..e87e57984d967 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_u8.ll @@ -0,0 +1,28 @@ +; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: [[int8:%.*]] = OpTypeInt 8 0 +; CHECK-DAG: [[int8x4:%.*]] = OpTypeVector [[int8]] 4 +; CHECK-DAG: [[int16:%.*]] = OpTypeInt 16 0 +; CHECK-DAG: [[int16x4:%.*]] = OpTypeVector [[int16]] 4 +; CHECK-DAG: [[int32:%.*]] = OpTypeInt 32 0 +; CHECK-DAG: [[int32x4:%.*]] = OpTypeVector [[int32]] 4 + +define noundef i32 @pack_u8_16(<4 x i16> noundef %a) { +; CHECK: [[in:%.*]] = OpFunctionParameter [[int16x4]] +; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[in]] +; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]] + %packed = call i32 @llvm.spv.pack.u8.v4i16(<4 x i16> %a) + ret i32 %packed +} + +define noundef i32 @pack_u8_32(<4 x i32> noundef %a) { +; CHECK: [[in:%.*]] = OpFunctionParameter [[int32x4]] +; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[in]] +; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]] + %packed = call i32 @llvm.spv.pack.u8.v4i32(<4 x i32> %a) + ret i32 %packed +} + +declare i32 @llvm.spv.pack.u8.v4i16(<4 x i16>) +declare i32 @llvm.spv.pack.u8.v4i32(<4 x i32>) >From b12322e01f986434cfdbbfe90cb1de399fbc8b42 Mon Sep 17 00:00:00 2001 From: Alexander Johnston <[email protected]> Date: Tue, 22 Sep 2026 13:23:08 +0100 Subject: [PATCH 3/3] Add missing cases in lldb --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 5255ec835c0a4..ff2e46c1b58e0 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -4925,6 +4925,11 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type) { case clang::BuiltinType::NullPtr: return lldb::eEncodingUint; + // HLSL -- Packed Types +#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case clang::BuiltinType::Id: +#include "clang/Basic/HLSLPackedTypes.def" + return lldb::eEncodingUint; + case clang::BuiltinType::Kind::ARCUnbridgedCast: case clang::BuiltinType::Kind::BoundMember: case clang::BuiltinType::Kind::BuiltinFn: _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
