https://github.com/hekota updated 
https://github.com/llvm/llvm-project/pull/119755

>From 8cebb59304a1f893d94f2a758bc47a62f27c1b8b Mon Sep 17 00:00:00 2001
From: Helena Kotas <heko...@microsoft.com>
Date: Thu, 12 Dec 2024 11:37:46 -0800
Subject: [PATCH 1/2] [HLSL] Codegen for simple `cbuffer` blocks without
 embedded arrays or structs

---
 clang/include/clang/Basic/Attr.td             |   6 +-
 clang/lib/CodeGen/CGDeclCXX.cpp               |  12 +-
 clang/lib/CodeGen/CGHLSLRuntime.cpp           | 249 +++++++++++-------
 clang/lib/CodeGen/CGHLSLRuntime.h             |  45 +++-
 clang/lib/Sema/SemaHLSL.cpp                   |  15 +-
 .../ByteAddressBuffers-constructors.hlsl      |   8 +-
 .../builtins/RWBuffer-constructor.hlsl        |  10 +-
 .../StructuredBuffers-constructors.hlsl       |   8 +-
 clang/test/CodeGenHLSL/cbuf.hlsl              |  26 --
 clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl |  23 --
 clang/test/CodeGenHLSL/cbuffer.hlsl           |  67 +++++
 .../CodeGenHLSL/cbuffer_and_namespaces.hlsl   |  47 ++++
 .../CodeGenHLSL/cbuffer_with_packoffset.hlsl  |  33 +++
 ...uffer_with_static_global_and_function.hlsl |  28 ++
 .../static_global_and_function_in_cb.hlsl     |  17 --
 15 files changed, 392 insertions(+), 202 deletions(-)
 delete mode 100644 clang/test/CodeGenHLSL/cbuf.hlsl
 delete mode 100644 clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl
 create mode 100644 clang/test/CodeGenHLSL/cbuffer.hlsl
 create mode 100644 clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl
 create mode 100644 clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl
 create mode 100644 
clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl
 delete mode 100644 clang/test/CodeGenHLSL/static_global_and_function_in_cb.hlsl

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 90d2a2056fe1ba..f615f45a9524d8 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4711,9 +4711,9 @@ def HLSLPackOffset: HLSLAnnotationAttr {
   let Args = [IntArgument<"Subcomponent">, IntArgument<"Component">];
   let Documentation = [HLSLPackOffsetDocs];
   let AdditionalMembers = [{
-      unsigned getOffset() {
-        return subcomponent * 4 + component;
-      }
+  unsigned getOffsetInBytes() {
+    return subcomponent * 16 + component * 4;
+  }
   }];
 }
 
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index 2c3054605ee754..2869150a5e6648 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -886,6 +886,10 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
       ModuleInits.push_back(Fn);
     }
 
+  if (getLangOpts().HLSL && getHLSLRuntime().needsResourceBindingInitFn()) {
+    CXXGlobalInits.push_back(getHLSLRuntime().createResourceBindingInitFn());
+  }
+
   if (ModuleInits.empty() && CXXGlobalInits.empty() &&
       PrioritizedCXXGlobalInits.empty())
     return;
@@ -1127,14 +1131,6 @@ 
CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
       if (Decls[i])
         EmitRuntimeCall(Decls[i]);
 
-    if (getLangOpts().HLSL) {
-      CGHLSLRuntime &CGHLSL = CGM.getHLSLRuntime();
-      if (CGHLSL.needsResourceBindingInitFn()) {
-        llvm::Function *ResInitFn = CGHLSL.createResourceBindingInitFn();
-        Builder.CreateCall(llvm::FunctionCallee(ResInitFn), {});
-      }
-    }
-
     Scope.ForceCleanup();
 
     if (ExitBlock) {
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp 
b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index fb15b1993e74ad..82fae11bc7bc37 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -54,69 +54,110 @@ void addDxilValVersion(StringRef ValVersionStr, 
llvm::Module &M) {
   auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
   DXILValMD->addOperand(Val);
 }
+
 void addDisableOptimizations(llvm::Module &M) {
   StringRef Key = "dx.disable_optimizations";
   M.addModuleFlag(llvm::Module::ModFlagBehavior::Override, Key, 1);
 }
-// cbuffer will be translated into global variable in special address space.
-// If translate into C,
-// cbuffer A {
-//   float a;
-//   float b;
-// }
-// float foo() { return a + b; }
-//
-// will be translated into
-//
-// struct A {
-//   float a;
-//   float b;
-// } cbuffer_A __attribute__((address_space(4)));
-// float foo() { return cbuffer_A.a + cbuffer_A.b; }
-//
-// layoutBuffer will create the struct A type.
-// replaceBuffer will replace use of global variable a and b with cbuffer_A.a
-// and cbuffer_A.b.
-//
-void layoutBuffer(CGHLSLRuntime::Buffer &Buf, const DataLayout &DL) {
-  if (Buf.Constants.empty())
-    return;
+
+// Creates the LLVM struct type representing the shape of the constant buffer
+// which will be included in the LLVM target type and calculates the memory
+// layout and constant buffer layout offsets of each constant.
+static void layoutBuffer(CGHLSLRuntime::Buffer &Buf, const DataLayout &DL) {
+  assert(!Buf.Constants.empty() &&
+         "empty constant buffer should not be created");
 
   std::vector<llvm::Type *> EltTys;
-  for (auto &Const : Buf.Constants) {
-    GlobalVariable *GV = Const.first;
-    Const.second = EltTys.size();
+  unsigned MemOffset = 0, CBufOffset = 0, Size = 0;
+
+  for (auto &C : Buf.Constants) {
+    GlobalVariable *GV = C.GlobalVar;
     llvm::Type *Ty = GV->getValueType();
+
+    assert(!Ty->isArrayTy() && !Ty->isStructTy() &&
+           "arrays and structs in cbuffer are not yet implemened");
+
+    // scalar type, vector or matrix
     EltTys.emplace_back(Ty);
+    unsigned FieldSize = Ty->getScalarSizeInBits() / 8;
+    if (Ty->isVectorTy())
+      FieldSize *= cast<FixedVectorType>(Ty)->getNumElements();
+    assert(FieldSize <= 16 && "field side larger than constant buffer row");
+
+    // set memory layout offset (no padding)
+    C.MemOffset = MemOffset;
+    MemOffset += FieldSize;
+
+    // calculate cbuffer layout offset or update total cbuffer size from
+    // packoffset annotations
+    if (Buf.HasPackoffset) {
+      assert(C.CBufferOffset != UINT_MAX &&
+             "cbuffer offset should have been set from packoffset attribute");
+      unsigned OffsetAfterField = C.CBufferOffset + FieldSize;
+      if (Size < OffsetAfterField)
+        Size = OffsetAfterField;
+    } else {
+      // allign to the size of the field
+      CBufOffset = llvm::alignTo(CBufOffset, FieldSize);
+      C.CBufferOffset = CBufOffset;
+      CBufOffset += FieldSize;
+      Size = CBufOffset;
+    }
   }
   Buf.LayoutStruct = llvm::StructType::get(EltTys[0]->getContext(), EltTys);
+  Buf.Size = Size;
 }
 
-GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) {
-  // Create global variable for CB.
-  GlobalVariable *CBGV = new GlobalVariable(
-      Buf.LayoutStruct, /*isConstant*/ true,
-      GlobalValue::LinkageTypes::ExternalLinkage, nullptr,
-      llvm::formatv("{0}{1}", Buf.Name, Buf.IsCBuffer ? ".cb." : ".tb."),
-      GlobalValue::NotThreadLocal);
+// Creates LLVM target type target("dx.CBuffer",..) for the constant buffer.
+// The target type includes the LLVM struct type representing the shape
+// of the constant buffer, size, and a list of offsets for each fields
+// in cbuffer layout.
+static llvm::Type *getBufferTargetType(LLVMContext &Ctx,
+                                       CGHLSLRuntime::Buffer &Buf) {
+  assert(Buf.LayoutStruct != nullptr && Buf.Size != UINT_MAX &&
+         "the buffer layout has not been calculated yet");
+  llvm::SmallVector<unsigned> SizeAndOffsets;
+  SizeAndOffsets.reserve(Buf.Constants.size() + 1);
+  SizeAndOffsets.push_back(Buf.Size);
+  for (CGHLSLRuntime::BufferConstant &C : Buf.Constants) {
+    SizeAndOffsets.push_back(C.CBufferOffset);
+  }
+  return llvm::TargetExtType::get(Ctx, "dx.CBuffer", {Buf.LayoutStruct},
+                                  SizeAndOffsets);
+}
 
-  IRBuilder<> B(CBGV->getContext());
-  Value *ZeroIdx = B.getInt32(0);
-  // Replace Const use with CB use.
-  for (auto &[GV, Offset] : Buf.Constants) {
-    Value *GEP =
-        B.CreateGEP(Buf.LayoutStruct, CBGV, {ZeroIdx, B.getInt32(Offset)});
-
-    assert(Buf.LayoutStruct->getElementType(Offset) == GV->getValueType() &&
-           "constant type mismatch");
-
-    // Replace.
-    GV->replaceAllUsesWith(GEP);
-    // Erase GV.
-    GV->removeDeadConstantUsers();
-    GV->eraseFromParent();
+// Replaces all uses of the temporary constant buffer global variables with
+// buffer access intrinsic resource.getpointer.
+static void replaceBufferGlobals(CodeGenModule &CGM,
+                                 CGHLSLRuntime::Buffer &Buf) {
+  assert(Buf.IsCBuffer && "tbuffer codegen is not yet supported");
+
+  GlobalVariable *BufGV = Buf.GlobalVar;
+  for (auto &Constant : Buf.Constants) {
+    GlobalVariable *ConstGV = Constant.GlobalVar;
+
+    // TODO: Map to an hlsl_device address space.
+    llvm::Type *RetTy = ConstGV->getType();
+    llvm::Type *TargetTy = BufGV->getValueType();
+
+    // Replace all uses of GV with CBuffer access
+    while (ConstGV->use_begin() != ConstGV->use_end()) {
+      Use &U = *ConstGV->use_begin();
+      if (Instruction *UserInstr = dyn_cast<Instruction>(U.getUser())) {
+        IRBuilder<> Builder(UserInstr);
+        Value *Handle = Builder.CreateLoad(TargetTy, BufGV);
+        Value *ResGetPointer = Builder.CreateIntrinsic(
+            RetTy, Intrinsic::dx_resource_getpointer,
+            ArrayRef<llvm::Value *>{Handle,
+                                    Builder.getInt32(Constant.MemOffset)});
+        U.set(ResGetPointer);
+      } else {
+        llvm_unreachable("unexpected use of constant value");
+      }
+    }
+    ConstGV->removeDeadConstantUsers();
+    ConstGV->eraseFromParent();
   }
-  return CBGV;
 }
 
 } // namespace
@@ -143,6 +184,9 @@ void CGHLSLRuntime::addConstant(VarDecl *D, Buffer &CB) {
     return;
   }
 
+  assert(!D->getType()->isArrayType() && !D->getType()->isStructureType() &&
+         "codegen for arrays and structs in cbuffer is not yet supported");
+
   auto *GV = cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(D));
   // Add debug info for constVal.
   if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
@@ -150,13 +194,12 @@ void CGHLSLRuntime::addConstant(VarDecl *D, Buffer &CB) {
         codegenoptions::DebugInfoKind::LimitedDebugInfo)
       DI->EmitGlobalVariable(cast<GlobalVariable>(GV), D);
 
-  // FIXME: support packoffset.
-  // See https://github.com/llvm/llvm-project/issues/57914.
-  uint32_t Offset = 0;
-  bool HasUserOffset = false;
+  CB.Constants.emplace_back(GV);
 
-  unsigned LowerBound = HasUserOffset ? Offset : UINT_MAX;
-  CB.Constants.emplace_back(std::make_pair(GV, LowerBound));
+  if (HLSLPackOffsetAttr *PO = D->getAttr<HLSLPackOffsetAttr>()) {
+    CB.HasPackoffset = true;
+    CB.Constants.back().CBufferOffset = PO->getOffsetInBytes();
+  }
 }
 
 void CGHLSLRuntime::addBufferDecls(const DeclContext *DC, Buffer &CB) {
@@ -173,9 +216,37 @@ void CGHLSLRuntime::addBufferDecls(const DeclContext *DC, 
Buffer &CB) {
   }
 }
 
+// Creates temporary global variables for all declarations within the constant
+// buffer context, calculates the buffer layouts, and then creates a global
+// variable for the constant buffer and adds it to the module.
+// All uses of the temporary constant globals will be replaced with buffer
+// access intrinsic resource.getpointer in CGHLSLRuntime::finishCodeGen.
+// Later on in DXILResourceAccess pass these will be transtaled
+// to dx.op.cbufferLoadLegacy instructions.
 void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *D) {
-  Buffers.emplace_back(Buffer(D));
-  addBufferDecls(D, Buffers.back());
+  llvm::Module &M = CGM.getModule();
+  const DataLayout &DL = M.getDataLayout();
+
+  assert(D->isCBuffer() && "tbuffer codegen is not supported yet");
+
+  Buffer &Buf = Buffers.emplace_back(D);
+  addBufferDecls(D, Buf);
+  if (Buf.Constants.empty()) {
+    // empty constant buffer - do not add to globals
+    Buffers.pop_back();
+    return;
+  }
+  layoutBuffer(Buf, DL);
+
+  // Create global variable for CB.
+  llvm::Type *TargetTy = getBufferTargetType(CGM.getLLVMContext(), Buf);
+  Buf.GlobalVar = new GlobalVariable(
+      TargetTy, /*isConstant*/ true, 
GlobalValue::LinkageTypes::ExternalLinkage,
+      nullptr, llvm::formatv("{0}{1}", Buf.Name, Buf.IsCBuffer ? ".cb" : 
".tb"),
+      GlobalValue::NotThreadLocal);
+
+  M.insertGlobalVariable(Buf.GlobalVar);
+  ResourcesToBind.emplace_back(Buf.Decl, Buf.GlobalVar);
 }
 
 void CGHLSLRuntime::finishCodeGen() {
@@ -189,26 +260,14 @@ void CGHLSLRuntime::finishCodeGen() {
   if (CGM.getCodeGenOpts().OptimizationLevel == 0)
     addDisableOptimizations(M);
 
-  const DataLayout &DL = M.getDataLayout();
-
   for (auto &Buf : Buffers) {
-    layoutBuffer(Buf, DL);
-    GlobalVariable *GV = replaceBuffer(Buf);
-    M.insertGlobalVariable(GV);
-    llvm::hlsl::ResourceClass RC = Buf.IsCBuffer
-                                       ? llvm::hlsl::ResourceClass::CBuffer
-                                       : llvm::hlsl::ResourceClass::SRV;
-    llvm::hlsl::ResourceKind RK = Buf.IsCBuffer
-                                      ? llvm::hlsl::ResourceKind::CBuffer
-                                      : llvm::hlsl::ResourceKind::TBuffer;
-    addBufferResourceAnnotation(GV, RC, RK, /*IsROV=*/false,
-                                llvm::hlsl::ElementType::Invalid, Buf.Binding);
+    replaceBufferGlobals(CGM, Buf);
   }
 }
 
 CGHLSLRuntime::Buffer::Buffer(const HLSLBufferDecl *D)
-    : Name(D->getName()), IsCBuffer(D->isCBuffer()),
-      Binding(D->getAttr<HLSLResourceBindingAttr>()) {}
+    : Name(D->getName()), IsCBuffer(D->isCBuffer()), HasPackoffset(false),
+      LayoutStruct(nullptr), Decl(D), GlobalVar(nullptr) {}
 
 void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV,
                                                 llvm::hlsl::ResourceClass RC,
@@ -237,7 +296,7 @@ void 
CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV,
          "ResourceMD must have been set by the switch above.");
 
   llvm::hlsl::FrontendResource Res(
-      GV, RK, ET, IsROV, Binding.Reg.value_or(UINT_MAX), Binding.Space);
+      GV, RK, ET, IsROV, Binding.Slot.value_or(UINT_MAX), Binding.Space);
   ResourceMD->addOperand(Res.getMetadata());
 }
 
@@ -328,12 +387,8 @@ void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, 
GlobalVariable *GV) {
 CGHLSLRuntime::BufferResBinding::BufferResBinding(
     HLSLResourceBindingAttr *Binding) {
   if (Binding) {
-    llvm::APInt RegInt(64, 0);
-    Binding->getSlot().substr(1).getAsInteger(10, RegInt);
-    Reg = RegInt.getLimitedValue();
-    llvm::APInt SpaceInt(64, 0);
-    Binding->getSpace().substr(5).getAsInteger(10, SpaceInt);
-    Space = SpaceInt.getLimitedValue();
+    Slot = Binding->getSlotNumber();
+    Space = Binding->getSpaceNumber();
   } else {
     Space = 0;
   }
@@ -572,24 +627,30 @@ llvm::Function 
*CGHLSLRuntime::createResourceBindingInitFn() {
   const DataLayout &DL = CGM.getModule().getDataLayout();
   Builder.SetInsertPoint(EntryBB);
 
-  for (const auto &[VD, GV] : ResourcesToBind) {
-    for (Attr *A : VD->getAttrs()) {
+  for (const auto &[Decl, GV] : ResourcesToBind) {
+    for (Attr *A : Decl->getAttrs()) {
       HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
       if (!RBA)
         continue;
 
-      const HLSLAttributedResourceType *AttrResType =
-          HLSLAttributedResourceType::findHandleTypeOnResource(
-              VD->getType().getTypePtr());
-
-      // FIXME: Only simple declarations of resources are supported for now.
-      // Arrays of resources or resources in user defined classes are
-      // not implemented yet.
-      assert(AttrResType != nullptr &&
-             "Resource class must have a handle of 
HLSLAttributedResourceType");
-
-      llvm::Type *TargetTy =
-          CGM.getTargetCodeGenInfo().getHLSLType(CGM, AttrResType);
+      llvm::Type *TargetTy = nullptr;
+      if (const VarDecl *VD = dyn_cast<VarDecl>(Decl)) {
+        const HLSLAttributedResourceType *AttrResType =
+            HLSLAttributedResourceType::findHandleTypeOnResource(
+                VD->getType().getTypePtr());
+
+        // FIXME: Only simple declarations of resources are supported for now.
+        // Arrays of resources or resources in user defined classes are
+        // not implemented yet.
+        assert(
+            AttrResType != nullptr &&
+            "Resource class must have a handle of HLSLAttributedResourceType");
+
+        TargetTy = CGM.getTargetCodeGenInfo().getHLSLType(CGM, AttrResType);
+      } else {
+        assert(isa<HLSLBufferDecl>(Decl));
+        TargetTy = GV->getValueType();
+      }
       assert(TargetTy != nullptr &&
              "Failed to convert resource handle to target type");
 
@@ -604,7 +665,7 @@ llvm::Function 
*CGHLSLRuntime::createResourceBindingInitFn() {
 
       llvm::Value *CreateHandle = Builder.CreateIntrinsic(
           /*ReturnType=*/TargetTy, getCreateHandleFromBindingIntrinsic(), Args,
-          nullptr, Twine(VD->getName()).concat("_h"));
+          nullptr, Twine(Decl->getName()).concat("_h"));
 
       llvm::Value *HandleRef =
           Builder.CreateStructGEP(GV->getValueType(), GV, 0);
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index f9efb1bc996412..9c3bbf5bbfe190 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -15,6 +15,7 @@
 #ifndef LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H
 #define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H
 
+#include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/IntrinsicsDirectX.h"
@@ -53,6 +54,7 @@ class StructType;
 } // namespace llvm
 
 namespace clang {
+class NamedDecl;
 class VarDecl;
 class ParmVarDecl;
 class HLSLBufferDecl;
@@ -112,22 +114,43 @@ class CGHLSLRuntime {
   
//===----------------------------------------------------------------------===//
 
   struct BufferResBinding {
-    // The ID like 2 in register(b2, space1).
-    std::optional<unsigned> Reg;
-    // The Space like 1 is register(b2, space1).
-    // Default value is 0.
+    // Register slot
+    std::optional<unsigned> Slot;
+    // Register space; default value is 0.
     unsigned Space;
+
     BufferResBinding(HLSLResourceBindingAttr *Attr);
   };
+
+  struct BufferConstant {
+    llvm::GlobalVariable *GlobalVar;
+    // offset in memory layout (in bytes)
+    unsigned MemOffset;
+    // offset in cbuffer layout (in bytes)
+    unsigned CBufferOffset;
+
+    BufferConstant(llvm::GlobalVariable *GV)
+        : GlobalVar(GV), MemOffset(UINT_MAX), CBufferOffset(UINT_MAX) {}
+  };
+
   struct Buffer {
-    Buffer(const HLSLBufferDecl *D);
     llvm::StringRef Name;
-    // IsCBuffer - Whether the buffer is a cbuffer (and not a tbuffer).
+    // Whether the buffer is a cbuffer (and not a tbuffer).
     bool IsCBuffer;
-    BufferResBinding Binding;
-    // Global variable and offset for each constant.
-    std::vector<std::pair<llvm::GlobalVariable *, unsigned>> Constants;
-    llvm::StructType *LayoutStruct = nullptr;
+    // Whether the buffer has packoffset annotations
+    bool HasPackoffset;
+    // List of global constants with memory and cbuffer layout ofsets
+    std::vector<BufferConstant> Constants;
+    // LLVM layout type
+    llvm::StructType *LayoutStruct;
+    // size of the buffer in cbuffer layout
+    unsigned Size;
+    // reference to the AST Decl node with resource binding attribute
+    const HLSLBufferDecl *Decl;
+    // global variable for the constant buffer
+    llvm::GlobalVariable *GlobalVar;
+
+    Buffer(const HLSLBufferDecl *D);
   };
 
 protected:
@@ -169,7 +192,7 @@ class CGHLSLRuntime {
   llvm::Triple::ArchType getArch();
   llvm::SmallVector<Buffer> Buffers;
 
-  llvm::SmallVector<std::pair<const VarDecl *, llvm::GlobalVariable *>>
+  llvm::SmallVector<std::pair<const NamedDecl *, llvm::GlobalVariable *>>
       ResourcesToBind;
 };
 
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 600c800029fd05..9b96806c35f3da 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -164,18 +164,18 @@ Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool 
CBuffer,
   return Result;
 }
 
-// Calculate the size of a legacy cbuffer type based on
+// Calculate the size of a legacy cbuffer type in bytes based on
 // 
https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
 static unsigned calculateLegacyCbufferSize(const ASTContext &Context,
                                            QualType T) {
   unsigned Size = 0;
-  constexpr unsigned CBufferAlign = 128;
+  constexpr unsigned CBufferAlign = 16;
   if (const RecordType *RT = T->getAs<RecordType>()) {
     const RecordDecl *RD = RT->getDecl();
     for (const FieldDecl *Field : RD->fields()) {
       QualType Ty = Field->getType();
       unsigned FieldSize = calculateLegacyCbufferSize(Context, Ty);
-      unsigned FieldAlign = 32;
+      unsigned FieldAlign = 4;
       if (Ty->isAggregateType())
         FieldAlign = CBufferAlign;
       Size = llvm::alignTo(Size, FieldAlign);
@@ -194,7 +194,7 @@ static unsigned calculateLegacyCbufferSize(const ASTContext 
&Context,
         calculateLegacyCbufferSize(Context, VT->getElementType());
     Size = ElementSize * ElementCount;
   } else {
-    Size = Context.getTypeSize(T);
+    Size = Context.getTypeSize(T) / 8;
   }
   return Size;
 }
@@ -229,16 +229,17 @@ void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, 
SourceLocation RBrace) {
     std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
               [](const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
                  const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
-                return LHS.second->getOffset() < RHS.second->getOffset();
+                return LHS.second->getOffsetInBytes() <
+                       RHS.second->getOffsetInBytes();
               });
 
     for (unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
       VarDecl *Var = PackOffsetVec[i].first;
       HLSLPackOffsetAttr *Attr = PackOffsetVec[i].second;
       unsigned Size = calculateLegacyCbufferSize(Context, Var->getType());
-      unsigned Begin = Attr->getOffset() * 32;
+      unsigned Begin = Attr->getOffsetInBytes();
       unsigned End = Begin + Size;
-      unsigned NextBegin = PackOffsetVec[i + 1].second->getOffset() * 32;
+      unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();
       if (End > NextBegin) {
         VarDecl *NextVar = PackOffsetVec[i + 1].first;
         Diag(NextVar->getLocation(), diag::err_hlsl_packoffset_overlap)
diff --git 
a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl 
b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
index 45e135427ba9c3..f1e949ab652cce 100644
--- a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
@@ -15,10 +15,6 @@ RasterizerOrderedByteAddressBuffer Buffer2: register(u3, 
space4);
 // CHECK: @Buffer1 = global %"class.hlsl::RWByteAddressBuffer" 
zeroinitializer, align 4
 // CHECK: @Buffer2 = global %"class.hlsl::RasterizerOrderedByteAddressBuffer" 
zeroinitializer, align 4
 
-// CHECK: define internal void 
@_GLOBAL__sub_I_ByteAddressBuffers_constructors.hlsl()
-// CHECK: entry:
-// CHECK: call void @_init_resource_bindings()
-
 // CHECK: define internal void @_init_resource_bindings() {
 // CHECK-NEXT: entry:
 // CHECK-DXIL-NEXT: %Buffer0_h = call target("dx.RawBuffer", i8, 0, 0) 
@llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t(i32 0, i32 0, i32 1, i32 0, 
i1 false)
@@ -27,3 +23,7 @@ RasterizerOrderedByteAddressBuffer Buffer2: register(u3, 
space4);
 // CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 0) %Buffer1_h, ptr 
@Buffer1, align 4
 // CHECK-DXIL-NEXT: %Buffer2_h = call target("dx.RawBuffer", i8, 1, 1) 
@llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_1_1t(i32 4, i32 3, i32 1, i32 0, 
i1 false)
 // CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 1) %Buffer2_h, ptr 
@Buffer2, align 4
+
+// CHECK: define internal void 
@_GLOBAL__sub_I_ByteAddressBuffers_constructors.hlsl()
+// CHECK: entry:
+// CHECK: call void @_init_resource_bindings()
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl 
b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
index c2db56e2b2bddf..8f252ea357459a 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
@@ -12,14 +12,14 @@ RWBuffer<float> Buf : register(u5, space3);
 // CHECK: define linkonce_odr void @_ZN4hlsl8RWBufferIfEC2Ev(ptr noundef 
nonnull align 4 dereferenceable(4) %this)
 // CHECK-NEXT: entry:
 
-// CHECK: define internal void @_GLOBAL__sub_I_RWBuffer_constructor.hlsl()
-// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @__cxx_global_var_init()
-// CHECK-NEXT: call void @_init_resource_bindings()
-
 // CHECK: define internal void @_init_resource_bindings() {
 // CHECK-NEXT: entry:
 // CHECK-DXIL-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) 
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 
0, i1 false)
 // CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h, ptr 
@Buf, align 4
 // CHECK-SPIRV-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) 
@llvm.spv.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, 
i32 0, i1 false)
 // CHECK-SPIRV-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h, 
ptr @Buf, align 4
+
+// CHECK: define internal void @_GLOBAL__sub_I_RWBuffer_constructor.hlsl()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void @__cxx_global_var_init()
+// CHECK-NEXT: call void @_init_resource_bindings()
diff --git 
a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl 
b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
index d84e92242ffb4d..17cba38cc8283f 100644
--- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
@@ -31,10 +31,6 @@ RasterizerOrderedStructuredBuffer<float> Buf5 : register(u1, 
space2);
 // CHECK: define linkonce_odr void 
@_ZN4hlsl33RasterizerOrderedStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 
dereferenceable(4) %this)
 // CHECK-NEXT: entry:
 
-// CHECK: define internal void 
@_GLOBAL__sub_I_StructuredBuffers_constructors.hlsl()
-// CHECK: entry:
-// CHECK: call void @_init_resource_bindings()
-
 // CHECK: define internal void @_init_resource_bindings() {
 // CHECK-NEXT: entry:
 // CHECK-DXIL-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) 
@llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, 
i1 false)
@@ -58,3 +54,7 @@ RasterizerOrderedStructuredBuffer<float> Buf5 : register(u1, 
space2);
 // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf4_h, ptr 
@Buf4, align 4
 // CHECK-SPIRV-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) 
@llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, 
i1 false)
 // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr 
@Buf5, align 4
+
+// CHECK: define internal void 
@_GLOBAL__sub_I_StructuredBuffers_constructors.hlsl()
+// CHECK: entry:
+// CHECK: call void @_init_resource_bindings()
diff --git a/clang/test/CodeGenHLSL/cbuf.hlsl b/clang/test/CodeGenHLSL/cbuf.hlsl
deleted file mode 100644
index 3f9d4514967dd2..00000000000000
--- a/clang/test/CodeGenHLSL/cbuf.hlsl
+++ /dev/null
@@ -1,26 +0,0 @@
-// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
-// RUN:   dxil-pc-shadermodel6.3-library %s \
-// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s
-
-// CHECK: @[[CB:.+]] = external constant { float, double }
-cbuffer A : register(b0, space2) {
-  float a;
-  double b;
-}
-
-// CHECK: @[[TB:.+]] = external constant { float, double }
-tbuffer A : register(t2, space1) {
-  float c;
-  double d;
-}
-
-float foo() {
-// CHECK: load float, ptr @[[CB]], align 4
-// CHECK: load double, ptr getelementptr ({ float, double }, ptr @[[CB]], i32 
0, i32 1), align 8
-// CHECK: load float, ptr @[[TB]], align 4
-// CHECK: load double, ptr getelementptr ({ float, double }, ptr @[[TB]], i32 
0, i32 1), align 8
-  return a + b + c*d;
-}
-
-// CHECK: !hlsl.cbufs = !{![[CBMD:[0-9]+]]}
-// CHECK: ![[CBMD]] = !{ptr @[[CB]], i32 13, i32 0, i1 false, i32 0, i32 2}
diff --git a/clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl 
b/clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl
deleted file mode 100644
index 73dc376942dfb7..00000000000000
--- a/clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
-// RUN:   dxil-pc-shadermodel6.3-library %s \
-// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s
-
-// Make sure cbuffer inside namespace works.
-// CHECK: @[[CB:.+]] = external constant { float }
-// CHECK: @[[TB:.+]] = external constant { float }
-namespace n0 {
-namespace n1 {
-  cbuffer A {
-    float a;
-  }
-}
-  tbuffer B {
-    float b;
-  }
-}
-
-float foo() {
-// CHECK: load float, ptr @[[CB]], align 4
-// CHECK: load float, ptr @[[TB]], align 4
-  return n0::n1::a + n0::b;
-}
diff --git a/clang/test/CodeGenHLSL/cbuffer.hlsl 
b/clang/test/CodeGenHLSL/cbuffer.hlsl
new file mode 100644
index 00000000000000..4d6b55157f30a5
--- /dev/null
+++ b/clang/test/CodeGenHLSL/cbuffer.hlsl
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-compute %s \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+
+// CHECK: @CB1.cb = external constant target("dx.CBuffer", { float, double }, 
16, 0, 8)
+cbuffer CB1 : register(b0, space2) {
+  float a;
+  double b;
+}
+
+// CHECK: @ParticleLifeCB.cb = external constant target("dx.CBuffer", { i32, 
i32, <2 x float>, float, float }, 24, 0, 4, 8, 16, 20)
+cbuffer ParticleLifeCB : register(b2, space1) {
+  uint ParticleTypeMax;
+  uint NumParticles;
+  float2 WorldSize;
+  float Friction;
+  float ForceMultipler;
+}
+
+float foo() {
+// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", { float, double }, 
16, 0, 8), ptr @CB1.cb, align 4
+// CHECK: %[[PTR1:[0-9]+]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_16_0_8t(target("dx.CBuffer",
 { float, double }, 16, 0, 8) %[[HANDLE1]], i32 0)
+// CHECK: load float, ptr %[[PTR1]], align 4
+
+// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", { float, double }, 
16, 0, 8), ptr @CB1.cb, align 4  
+// CHECK: %[[PTR2:[0-9]+]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_16_0_8t(target("dx.CBuffer",
 { float, double }, 16, 0, 8) %[[HANDLE2]], i32 4)
+// CHECK: load double, ptr %[[PTR2]], align 8
+  
+// CHECK: %[[HANDLE3:[0-9]+]] = load target("dx.CBuffer", { i32, i32, <2 x 
float>, float, float }, 24, 0, 4, 8, 16, 20), ptr @ParticleLifeCB.cb, align 4
+// CHECK: %[[PTR3:[0-9]+]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t(
+// CHECK-SAME: target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 
24, 0, 4, 8, 16, 20) %[[HANDLE3]], i32 0)
+// CHECK: load i32, ptr %[[PTR3]], align 4
+
+// CHECK: %[[HANDLE4:[0-9]+]] = load target("dx.CBuffer", { i32, i32, <2 x 
float>, float, float }, 24, 0, 4, 8, 16, 20), ptr @ParticleLifeCB.cb, align 4
+// CHECK: %[[PTR4:[0-9]+]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t(
+// CHECK-SAME: target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 
24, 0, 4, 8, 16, 20) %[[HANDLE4]], i32 8)
+// CHECK: load <2 x float>, ptr %[[PTR4]], align 8
+
+// CHECK: %[[HANDLE5:[0-9]+]] = load target("dx.CBuffer", { i32, i32, <2 x 
float>, float, float }, 24, 0, 4, 8, 16, 20), ptr @ParticleLifeCB.cb, align 4
+// CHECK: %[[PTR5:[0-9]+]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t(
+// CHECK-SAME: target("dx.CBuffer", { i32, i32, <2 x float>, float, float }, 
24, 0, 4, 8, 16, 20) %[[HANDLE5]], i32 20)
+// CHECK: load float, ptr %[[PTR5]], align 4
+  return a + b + ParticleTypeMax + WorldSize.y * ForceMultipler;
+}
+
+// CHECK: define void @main()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void @_GLOBAL__sub_I_cbuffer.hlsl()
+// CHECK-NEXT: call void @_Z4mainv()
+// CHECK-NEXT: ret void
+
+// CHECK: define internal void @_init_resource_bindings() {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %CB1_h = call target("dx.CBuffer", { float, double }, 16, 0, 8)
+// CHECK-SAME: @llvm.dx.handle.fromBinding.tdx.CBuffer_sl_f32f64s_16_0_8t(i32 
2, i32 0, i32 1, i32 0, i1 false)
+// CHECK-NEXT: store target("dx.CBuffer", { float, double }, 16, 0, 8) %CB1_h, 
ptr @CB1.cb, align 4
+// CHECK-NEXT: %ParticleLifeCB_h = call target("dx.CBuffer", { i32, i32, <2 x 
float>, float, float }, 24, 0, 4, 8, 16, 20)
+// CHECK-SAME: 
@llvm.dx.handle.fromBinding.tdx.CBuffer_sl_i32i32v2f32f32f32s_24_0_4_8_16_20t(i32
 1, i32 2, i32 1, i32 0, i1 false)
+// CHECK-NEXT: store target("dx.CBuffer", { i32, i32, <2 x float>, float, 
float }, 24, 0, 4, 8, 16, 20) %ParticleLifeCB_h, ptr @ParticleLifeCB.cb, align 4
+
+// CHECK: define internal void @_GLOBAL__sub_I_cbuffer.hlsl()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void @_init_resource_bindings()
+// CHECK-NEXT: ret void
+
+[numthreads(4,1,1)]
+void main() {}
diff --git a/clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl 
b/clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl
new file mode 100644
index 00000000000000..860716ad3e582a
--- /dev/null
+++ b/clang/test/CodeGenHLSL/cbuffer_and_namespaces.hlsl
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+
+// Make sure cbuffer inside namespace works.
+// CHECK: @A.cb = external constant target("dx.CBuffer", { float }, 4, 0)
+// CHECK: @B.cb = external constant target("dx.CBuffer", { float }, 4, 0)
+// CHECK: @C.cb = external constant target("dx.CBuffer", { float }, 4, 0)
+
+namespace n0 {
+  namespace n1 {
+    cbuffer A {
+      float a;
+    }
+  }
+  cbuffer B {
+    float a;
+  }
+  namespace n2 {
+    cbuffer C {
+      float a;
+    }
+  }
+}
+
+float foo() {
+// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), 
ptr @A.cb, align 4
+// CHECK: %[[PTR1:[0-9]+]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { 
float }, 4, 0) %[[HANDLE1]], i32 0)
+// CHECK: %[[VAL1:[0-9]+]] = load float, ptr %[[PTR1]], align 4
+
+// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), 
ptr @B.cb, align 4
+// CHECK: %[[PTR2:[0-9]+]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { 
float }, 4, 0) %[[HANDLE2]], i32 0)
+// CHECK: %[[VAL2:[0-9]+]] = load float, ptr %[[PTR2]], align 4
+
+// CHECK: %add = fadd float %[[VAL1]], %[[VAL2]]
+
+// CHECK: %[[HANDLE3:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), 
ptr @C.cb, align 4
+// CHECK: %[[PTR3:[0-9]+]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { 
float }, 4, 0) %[[HANDLE3]], i32 0)
+// CHECK: %[[VAL3:[0-9]+]] = load float, ptr %[[PTR3]], align 4
+
+// CHECK: %add1 = fadd float %add, %[[VAL3]]
+
+  return n0::n1::a + n0::a + n0::n2::a;
+}
+
+[numthreads(4,1,1)]
+void main() {}
diff --git a/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl 
b/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl
new file mode 100644
index 00000000000000..58891659179aed
--- /dev/null
+++ b/clang/test/CodeGenHLSL/cbuffer_with_packoffset.hlsl
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-compute %s \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+
+// CHECK: @CB.cb = external constant target("dx.CBuffer", { float, double }, 
176, 16, 168)
+cbuffer CB : register(b1, space3) {
+  float a : packoffset(c1.x);
+  double b : packoffset(c10.z);
+}
+
+float foo() {
+// CHECK: %[[HANDLE1:[0-9]+]] = load target("dx.CBuffer", { float, double }, 
176, 16, 168), ptr @CB.cb, align 4
+// CHECK: %[[PTR1:[0-9]+]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_176_16_168t(
+// CHECK-SAME: target("dx.CBuffer", { float, double }, 176, 16, 168) 
%[[HANDLE1]], i32 0)
+// CHECK: load float, ptr %[[PTR1]], align 4
+
+// CHECK: %[[HANDLE2:[0-9]+]] = load target("dx.CBuffer", { float, double }, 
176, 16, 168), ptr @CB.cb, align 4
+// CHECK: %[[PTR2:[0-9]+]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32f64s_176_16_168t(
+// CHECK-SAME: target("dx.CBuffer", { float, double }, 176, 16, 168) 
%[[HANDLE2]], i32 4)
+// CHECK: load double, ptr %[[PTR2]], align 8
+  return a + b;
+}
+
+// CHECK: define internal void @_init_resource_bindings() {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %CB_h = call target("dx.CBuffer", { float, double }, 176, 16, 
168)
+// CHECK-SAME: 
@llvm.dx.handle.fromBinding.tdx.CBuffer_sl_f32f64s_176_16_168t(i32 3, i32 1, 
i32 1, i32 0, i1 false)
+// CHECK-NEXT: store target("dx.CBuffer", { float, double }, 176, 16, 168) 
%CB_h, ptr @CB.cb, align 4
+
+[numthreads(4,1,1)]
+void main() {
+  foo();
+}
diff --git 
a/clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl 
b/clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl
new file mode 100644
index 00000000000000..c72eac85ca675e
--- /dev/null
+++ b/clang/test/CodeGenHLSL/cbuffer_with_static_global_and_function.hlsl
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -finclude-default-header -triple 
dxil-pc-shadermodel6.3-library %s \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+
+// CHECK-DAG: @_ZL1b = internal global float 3.000000e+00, align 4
+// CHECK-DAG: @A.cb = external constant target("dx.CBuffer", { float }, 4, 0)
+// CHECK-NOT: @B.cb
+
+cbuffer A {
+  float a;
+  static float b = 3;
+  float foo() { return a + b; }
+}
+
+cbuffer B {
+  // intentionally empty
+}
+
+
+// CHECK: define noundef float @_Z3foov() #0 {
+// CHECK: %[[HANDLE:[0-9]+]] = load target("dx.CBuffer", { float }, 4, 0), ptr 
@A.cb, align 4
+// CHECK: %[[PTR:[0-9]+]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.CBuffer_sl_f32s_4_0t(target("dx.CBuffer", { 
float }, 4, 0) %[[HANDLE]], i32 0)
+// CHECK: %[[VAL1:[0-9]+]] = load float, ptr %[[PTR]], align 4
+// CHECK: %[[VAL2:[0-9]+]] = load float, ptr @_ZL1b, align 4
+// CHECK: %add = fadd float %[[VAL1]], %[[VAL2]]
+
+extern float bar() {
+  return foo();
+}
diff --git a/clang/test/CodeGenHLSL/static_global_and_function_in_cb.hlsl 
b/clang/test/CodeGenHLSL/static_global_and_function_in_cb.hlsl
deleted file mode 100644
index f85bab2113170b..00000000000000
--- a/clang/test/CodeGenHLSL/static_global_and_function_in_cb.hlsl
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %clang_cc1 -finclude-default-header -triple 
dxil-pc-shadermodel6.3-library %s \
-// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s
-
-// CHECK-DAG: @[[CB:.+]] = external constant { float }
-
-cbuffer A {
-    float a;
-  // CHECK-DAG:@_ZL1b = internal global float 3.000000e+00, align 4
-  static float b = 3;
-  // CHECK:load float, ptr @[[CB]], align 4
-  // CHECK:load float, ptr @_ZL1b, align 4
-  float foo() { return a + b; }
-}
-
-float bar() {
-  return foo();
-}

>From dee03ca52a009b3e71fe2c976aa59473a8d970cf Mon Sep 17 00:00:00 2001
From: Helena Kotas <heko...@microsoft.com>
Date: Thu, 12 Dec 2024 12:35:48 -0800
Subject: [PATCH 2/2] couple of commas to improve readability

---
 clang/lib/CodeGen/CGHLSLRuntime.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp 
b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 82fae11bc7bc37..cfa77ccd1054d6 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -60,8 +60,8 @@ void addDisableOptimizations(llvm::Module &M) {
   M.addModuleFlag(llvm::Module::ModFlagBehavior::Override, Key, 1);
 }
 
-// Creates the LLVM struct type representing the shape of the constant buffer
-// which will be included in the LLVM target type and calculates the memory
+// Creates the LLVM struct type representing the shape of the constant buffer,
+// which will be included in the LLVM target type, and calculates the memory
 // layout and constant buffer layout offsets of each constant.
 static void layoutBuffer(CGHLSLRuntime::Buffer &Buf, const DataLayout &DL) {
   assert(!Buf.Constants.empty() &&

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to