https://github.com/Alexander-Johnston created 
https://github.com/llvm/llvm-project/pull/224277

This patch adds the pack_u8/s8 and pack_clamp_u8/s8 intrinsics and the HLSL 
SM6.6 packed types they use.
The new types, int8_t4_packed and uint8_t4_packed, are convertible to uint as 
described in the DirectX Specs. They do not have the full breadth of DXCs 
implementation, which allows undefiend behaviour such as increment operators.

>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/2] [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/2] [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>)

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to