Jelajahi Sumber

Lower resource to createHandle at clang code gen. (#163)

* Lower resource to createHandle at clang code gen.
1. A HL createHandle will have 1 or 2 parameters.
   For  uav/srv/sampler, 1 parameter. 1 is the resource load from resource ptr.
   For cbuffer, 2 parameter. 1 is the same. 2 is for dynamic indexing on array of cbuffers.
   uav/srv/sampler don't have 2 is because all the use of them is on builtin methods. Resource on methods is scalar.
   createHandle function will have metadata to save the resource information like class/kind/type/...

2. Added 2 more passes DxilLegalizeResourceUsePass DxilLegalizeStaticResourceUsePass to remove load/store on local/static resource.
   Also make sure HL createHandle don't have phi operand.

3. For DxilGenerationPass,  Dxil createHandle will be generated after GenerateDxilOperations.
   And HLObjectOperationLowerHelper now get RK/RC from MetadataAsValue argument of HL createHandle.
Xiang Li 8 tahun lalu
induk
melakukan
a3306bff1d

+ 4 - 0
include/dxc/HLSL/DxilGenerationPass.h

@@ -43,6 +43,8 @@ ModulePass *createHLEmitMetadataPass();
 ModulePass *createHLEnsureMetadataPass();
 ModulePass *createDxilEmitMetadataPass();
 ModulePass *createDxilPrecisePropagatePass();
+FunctionPass *createDxilLegalizeResourceUsePass();
+ModulePass *createDxilLegalizeStaticResourceUsePass();
 FunctionPass *createDxilLegalizeSampleOffsetPass();
 FunctionPass *createSimplifyInstPass();
 
@@ -52,6 +54,8 @@ void initializeHLEnsureMetadataPass(llvm::PassRegistry&);
 void initializeHLEmitMetadataPass(llvm::PassRegistry&);
 void initializeDxilEmitMetadataPass(llvm::PassRegistry&);
 void initializeDxilPrecisePropagatePassPass(llvm::PassRegistry&);
+void initializeDxilLegalizeResourceUsePassPass(llvm::PassRegistry&);
+void initializeDxilLegalizeStaticResourceUsePassPass(llvm::PassRegistry&);
 void initializeDxilLegalizeSampleOffsetPassPass(llvm::PassRegistry&);
 void initializeSimplifyInstPass(llvm::PassRegistry&);
 

+ 3 - 0
include/dxc/HLSL/DxilMetadataHelper.h

@@ -172,6 +172,9 @@ public:
   // Control flow hint.
   static const char kDxilControlFlowHintMDName[];
 
+  // Resource attribute.
+  static const char kDxilResourceAttributeMDName[];
+
   // Precise attribute.
   static const char kDxilPreciseAttributeMDName[];
 

+ 11 - 1
include/dxc/HLSL/HLModule.h

@@ -29,6 +29,7 @@ class LLVMContext;
 class Module;
 class Function;
 class Instruction;
+class CallInst;
 class MDTuple;
 class MDNode;
 class GlobalVariable;
@@ -181,6 +182,12 @@ public:
   void LoadHLMetadata();
   /// Delete any HLDXIR from the specified module.
   static void ClearHLMetadata(llvm::Module &M);
+  /// Create Metadata from a resource.
+  llvm::MDNode *DxilSamplerToMDNode(const DxilSampler &S);
+  llvm::MDNode *DxilSRVToMDNode(const DxilResource &SRV);
+  llvm::MDNode *DxilUAVToMDNode(const DxilResource &UAV);
+  llvm::MDNode *DxilCBufferToMDNode(const DxilCBuffer &CB);
+  DxilResourceBase LoadDxilResourceBaseFromMDNode(llvm::MDNode *MD);
 
   // Type related methods.
   static bool IsStreamOutputPtrType(llvm::Type *Ty);
@@ -198,7 +205,7 @@ public:
 
   // HL code gen.
   template<class BuilderTy>
-  static llvm::Value *EmitHLOperationCall(BuilderTy &Builder,
+  static llvm::CallInst *EmitHLOperationCall(BuilderTy &Builder,
                                           HLOpcodeGroup group, unsigned opcode,
                                           llvm::Type *RetType,
                                           llvm::ArrayRef<llvm::Value *> paramList,
@@ -217,6 +224,9 @@ public:
   static void MarkPreciseAttributeOnPtrWithFunctionCall(llvm::Value *Ptr,
                                                         llvm::Module &M);
   static bool HasPreciseAttribute(llvm::Function *F);
+  // Resource attribute.
+  static void  MarkDxilResourceAttrib(llvm::Function *F, llvm::MDNode *MD);
+  static llvm::MDNode *GetDxilResourceAttrib(llvm::Function *F);
 
   // DXIL type system.
   DxilTypeSystem &GetTypeSystem();

+ 5 - 3
include/dxc/HLSL/HLOperationLower.h

@@ -10,10 +10,12 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 #pragma once
+#include <unordered_set>
 
 namespace llvm {
 class Instruction;
 class Value;
+class LoadInst;
 class Function;
 }
 
@@ -23,7 +25,7 @@ class DxilResourceBase;
 class HLSLExtensionsCodegenHelper;
 
 void TranslateBuiltinOperations(
-    HLModule &HLM,
-    std::unordered_map<llvm::Instruction *, llvm::Value *> &handleMap,
-    HLSLExtensionsCodegenHelper *extCodegenHelper);
+    HLModule &HLM, HLSLExtensionsCodegenHelper *extCodegenHelper,
+    std::unordered_set<llvm::LoadInst *> &UpdateCounterSet,
+    std::unordered_set<llvm::Value *> &NonUniformSet);
 }

+ 2 - 5
include/dxc/HLSL/HLOperationLowerExtension.h

@@ -39,11 +39,9 @@ namespace hlsl {
       Resource,       // Convert return value to resource return and explode vectors.
     };
 
-    typedef std::unordered_map<llvm::Instruction *, llvm::Value *> HandleMap;
-
     // Create the lowering using the given strategy and custom codegen helper.
-    ExtensionLowering(llvm::StringRef strategy, HLSLExtensionsCodegenHelper *helper, const HandleMap &handleMap, OP& hlslOp);
-    ExtensionLowering(Strategy strategy, HLSLExtensionsCodegenHelper *helper, const HandleMap &handleMap, OP& hlslOp);
+    ExtensionLowering(llvm::StringRef strategy, HLSLExtensionsCodegenHelper *helper, OP& hlslOp);
+    ExtensionLowering(Strategy strategy, HLSLExtensionsCodegenHelper *helper, OP& hlslOp);
 
     // Translate the HL op call to a DXIL op call.
     // Returns a new value if translation was successful.
@@ -69,7 +67,6 @@ namespace hlsl {
   private:
     Strategy m_strategy;
     HLSLExtensionsCodegenHelper *m_helper;
-    const HandleMap &m_handleMap;
     OP &m_hlslOp;
 
     llvm::Value *Unknown(llvm::CallInst *CI);

+ 6 - 1
include/dxc/HLSL/HLOperations.h

@@ -35,6 +35,7 @@ enum class HLOpcodeGroup {
   HLSubscript,
   HLMatLoadStore,
   HLSelect,
+  HLCreateHandle,
   NumOfHLOps
 };
 
@@ -111,7 +112,7 @@ enum class HLMatLoadStoreOpcode {
 extern const char * const HLPrefix;
 
 HLOpcodeGroup GetHLOpcodeGroup(llvm::Function *F);
-HLOpcodeGroup GetHLOpcodeGroupByName(llvm::Function *F);
+HLOpcodeGroup GetHLOpcodeGroupByName(const llvm::Function *F);
 llvm::StringRef GetHLOpcodeGroupNameByAttr(llvm::Function *F);
 llvm::StringRef GetHLLowerStrategy(llvm::Function *F);
 unsigned  GetHLOpcode(llvm::CallInst *CI);
@@ -321,6 +322,10 @@ const unsigned kGetDimensionsNoMipWidthOpIndex = 2;
 // WaveAllEqual.
 const unsigned kWaveAllEqualValueOpIdx = 1;
 
+// CreateHandle.
+const unsigned kCreateHandleResourceOpIdx = 1;
+const unsigned kCreateHandleIndexOpIdx = 2; // Only for array of cbuffer.
+
 } // namespace HLOperandIndex
 
 llvm::Function *GetOrCreateHLFunction(llvm::Module &M,

+ 2 - 0
lib/HLSL/DxcOptimizer.cpp

@@ -76,7 +76,9 @@ HRESULT SetupRegistryPassForHLSL() {
     initializeDxilCondenseResourcesPass(Registry);
     initializeDxilEmitMetadataPass(Registry);
     initializeDxilGenerationPassPass(Registry);
+    initializeDxilLegalizeResourceUsePassPass(Registry);
     initializeDxilLegalizeSampleOffsetPassPass(Registry);
+    initializeDxilLegalizeStaticResourceUsePassPass(Registry);
     initializeDxilPrecisePropagatePassPass(Registry);
     initializeDynamicIndexingVectorToArrayPass(Registry);
     initializeEarlyCSELegacyPassPass(Registry);

File diff ditekan karena terlalu besar
+ 343 - 465
lib/HLSL/DxilGenerationPass.cpp


+ 1 - 0
lib/HLSL/DxilMetadataHelper.cpp

@@ -44,6 +44,7 @@ const char DxilMDHelper::kDxilTypeSystemMDName[]                      = "dx.type
 const char DxilMDHelper::kDxilTypeSystemHelperVariablePrefix[]        = "dx.typevar.";
 const char DxilMDHelper::kDxilControlFlowHintMDName[]                 = "dx.controlflow.hints";
 const char DxilMDHelper::kDxilPreciseAttributeMDName[]                = "dx.precise";
+const char DxilMDHelper::kDxilResourceAttributeMDName[]               = "dx.resource.attribute";
 const char DxilMDHelper::kDxilValidatorVersionMDName[]                = "dx.valver";
 
 // This named metadata is not valid in final module (should be moved to DxilContainer)

+ 78 - 2
lib/HLSL/HLModule.cpp

@@ -710,6 +710,74 @@ void HLModule::LoadHLShaderProperties(const MDOperand &MDO) {
   return;
 }
 
+MDNode *HLModule::DxilSamplerToMDNode(const DxilSampler &S) {
+  MDNode *MD = m_pMDHelper->EmitDxilSampler(S);
+  ValueAsMetadata *ResClass =
+      m_pMDHelper->Uint32ToConstMD((unsigned)DXIL::ResourceClass::Sampler);
+
+  return MDNode::get(m_Ctx, {ResClass, MD});
+}
+MDNode *HLModule::DxilSRVToMDNode(const DxilResource &SRV) {
+  MDNode *MD = m_pMDHelper->EmitDxilSRV(SRV);
+  ValueAsMetadata *ResClass =
+      m_pMDHelper->Uint32ToConstMD((unsigned)DXIL::ResourceClass::SRV);
+
+  return MDNode::get(m_Ctx, {ResClass, MD});
+}
+MDNode *HLModule::DxilUAVToMDNode(const DxilResource &UAV) {
+  MDNode *MD = m_pMDHelper->EmitDxilUAV(UAV);
+  ValueAsMetadata *ResClass =
+      m_pMDHelper->Uint32ToConstMD((unsigned)DXIL::ResourceClass::UAV);
+
+  return MDNode::get(m_Ctx, {ResClass, MD});
+}
+MDNode *HLModule::DxilCBufferToMDNode(const DxilCBuffer &CB) {
+  MDNode *MD = m_pMDHelper->EmitDxilCBuffer(CB);
+  ValueAsMetadata *ResClass =
+      m_pMDHelper->Uint32ToConstMD((unsigned)DXIL::ResourceClass::CBuffer);
+
+  return MDNode::get(m_Ctx, {ResClass, MD});
+}
+
+DxilResourceBase HLModule::LoadDxilResourceBaseFromMDNode(
+                                              MDNode *MD) {
+  const unsigned kDxilResourceAttributeNumFields = 2;
+  const unsigned kDxilResourceAttributeClass = 0;
+  const unsigned kDxilResourceAttributeMeta = 1;
+  IFTBOOL(MD->getNumOperands() >= kDxilResourceAttributeNumFields,
+          DXC_E_INCORRECT_DXIL_METADATA);
+
+  DxilResource::Class RC =
+      static_cast<DxilResource::Class>(m_pMDHelper->ConstMDToUint32(
+          MD->getOperand(kDxilResourceAttributeClass)));
+  switch (RC) {
+  case DxilResource::Class::CBuffer: {
+    DxilCBuffer CB;
+    m_pMDHelper->LoadDxilCBuffer(MD->getOperand(kDxilResourceAttributeMeta),
+                                 CB);
+    return CB;
+  } break;
+  case DxilResource::Class::Sampler: {
+    DxilSampler S;
+    m_pMDHelper->LoadDxilSampler(MD->getOperand(kDxilResourceAttributeMeta), S);
+    return S;
+  } break;
+  case DxilResource::Class::SRV: {
+    DxilResource Res;
+    m_pMDHelper->LoadDxilSRV(MD->getOperand(kDxilResourceAttributeMeta), Res);
+    return Res;
+  } break;
+  case DxilResource::Class::UAV: {
+    DxilResource Res;
+    m_pMDHelper->LoadDxilUAV(MD->getOperand(kDxilResourceAttributeMeta), Res);
+    return Res;
+  } break;
+  default:
+    DXASSERT(0, "Invalid metadata");
+    return DxilResourceBase(DXIL::ResourceClass::Invalid);
+  }
+}
+
 // TODO: Don't check names.
 bool HLModule::IsStreamOutputType(llvm::Type *Ty) {
   if (StructType *ST = dyn_cast<StructType>(Ty)) {
@@ -891,7 +959,7 @@ const char *HLModule::GetLegacyDataLayoutDesc() {
 }
 
 template<typename BuilderTy>
-Value *HLModule::EmitHLOperationCall(BuilderTy &Builder,
+CallInst *HLModule::EmitHLOperationCall(BuilderTy &Builder,
                                            HLOpcodeGroup group, unsigned opcode,
                                            Type *RetType,
                                            ArrayRef<Value *> paramList,
@@ -918,7 +986,7 @@ Value *HLModule::EmitHLOperationCall(BuilderTy &Builder,
 }
 
 template
-Value *HLModule::EmitHLOperationCall(IRBuilder<> &Builder,
+CallInst *HLModule::EmitHLOperationCall(IRBuilder<> &Builder,
                                            HLOpcodeGroup group, unsigned opcode,
                                            Type *RetType,
                                            ArrayRef<Value *> paramList,
@@ -1059,6 +1127,14 @@ bool HLModule::HasPreciseAttribute(Function *F) {
   return preciseNode != nullptr;
 }
 
+void HLModule::MarkDxilResourceAttrib(llvm::Function *F, MDNode *MD) {
+  F->setMetadata(DxilMDHelper::kDxilResourceAttributeMDName, MD);
+}
+
+MDNode *HLModule::GetDxilResourceAttrib(llvm::Function *F) {
+  return F->getMetadata(DxilMDHelper::kDxilResourceAttributeMDName);
+}
+
 DIGlobalVariable *
 HLModule::FindGlobalVariableDebugInfo(GlobalVariable *GV,
                                       DebugInfoFinder &DbgInfoFinder) {

+ 168 - 150
lib/HLSL/HLOperationLower.cpp

@@ -58,70 +58,145 @@ HLOperationLowerHelper::HLOperationLowerHelper(HLModule &HLM)
 struct HLObjectOperationLowerHelper {
 private:
   // For object intrinsics.
-  std::unordered_map<llvm::Instruction *, llvm::Value *> &handleMap;
   HLModule &HLM;
+  struct ResAttribute {
+    DXIL::ResourceClass RC;
+    DXIL::ResourceKind RK;
+    Type *ResourceType;
+  };
+  std::unordered_map<Value *, ResAttribute> HandleMetaMap;
+  std::unordered_set<LoadInst *> &UpdateCounterSet;
+  std::unordered_set<Value *> &NonUniformSet;
+
 public:
-  HLObjectOperationLowerHelper(std::unordered_map<llvm::Instruction *, llvm::Value *> &handleMap,
-  HLModule &HLM) : HLM(HLM), handleMap(handleMap) {
+  HLObjectOperationLowerHelper(HLModule &HLM,
+                               std::unordered_set<LoadInst *> &UpdateCounter,
+                               std::unordered_set<Value *> &NonUniform)
+      : HLM(HLM), UpdateCounterSet(UpdateCounter), NonUniformSet(NonUniform) {}
+
+  DXIL::ResourceClass GetRC(Value *Handle) {
+    ResAttribute &Res = FindCreateHandleResourceBase(Handle);
+    return Res.RC;
   }
-  DXIL::ResourceClass GetRC(Type *Ty) {
-    return HLM.GetResourceClass(Ty);
+  DXIL::ResourceKind  GetRK(Value *Handle) {
+    ResAttribute &Res = FindCreateHandleResourceBase(Handle);
+    return Res.RK;
   }
-  DXIL::ResourceKind  GetRK(Type *Ty) {
-    return HLM.GetResourceKind(Ty);
+  Type *GetResourceType(Value *Handle) {
+    ResAttribute &Res = FindCreateHandleResourceBase(Handle);
+    return Res.ResourceType;
   }
 
   void MarkHasCounter(Type *Ty, Value *handle) {
-    DXIL::ResourceClass RC = GetRC(Ty);
+    DXIL::ResourceClass RC = GetRC(handle);
     DXASSERT_LOCALVAR(RC, RC == DXIL::ResourceClass::UAV, "must UAV for counter");
-    CallInst *CI = cast<CallInst>(handle);
-    Value *resID =
-        CI->getArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx);
-
-    std::vector<unsigned> immResIDs;
-    if (ConstantInt *constResID = dyn_cast<ConstantInt>(resID)) {
-      immResIDs.emplace_back(constResID->getValue().getLimitedValue());
-    } else {
-      PHINode *phi = cast<PHINode>(resID);
-      std::unordered_set<Value *> resSet;
-      CollectImmFromPhiChain(phi, immResIDs, resSet);
-    }
+    std::unordered_set<Value*> resSet;
+    MarkHasCounterOnCreateHandle(handle, resSet);
+  }
+  void MarkNonUniform(Value *V) {
+    NonUniformSet.insert(V);
+  }
+private:
+  ResAttribute &FindCreateHandleResourceBase(Value *Handle) {
+    if (HandleMetaMap.count(Handle))
+      return HandleMetaMap[Handle];
+
+    // Add invalid first to avoid dead loop.
+    HandleMetaMap[Handle] = {DXIL::ResourceClass::Invalid,
+                             DXIL::ResourceKind::Invalid,
+                             StructType::get(Type::getVoidTy(HLM.GetCtx()))};
+
+    if (CallInst *CI = dyn_cast<CallInst>(Handle)) {
+      MDNode *MD = HLM.GetDxilResourceAttrib(CI->getCalledFunction());
+      if (!MD) {
+        Handle->getContext().emitError("cannot map resource to handle");
+        return HandleMetaMap[Handle];
+      }
+      DxilResourceBase Res = HLM.LoadDxilResourceBaseFromMDNode(MD);
 
-    auto &uavs = HLM.GetUAVs();
+      ResAttribute Attrib = {Res.GetClass(), Res.GetKind(),
+                             Res.GetGlobalSymbol()->getType()};
 
-    for (unsigned i : immResIDs) {
-      uavs[i]->SetHasCounter(true);
+      HandleMetaMap[Handle] = Attrib;
+      return HandleMetaMap[Handle];
     }
+    if (SelectInst *Sel = dyn_cast<SelectInst>(Handle)) {
+      ResAttribute &ResT = FindCreateHandleResourceBase(Sel->getTrueValue());
+      // Use MDT here, ResourceClass, ResourceID match is done at
+      // DxilGenerationPass::AddCreateHandleForPhiNodeAndSelect.
+      HandleMetaMap[Handle] = ResT;
+      FindCreateHandleResourceBase(Sel->getFalseValue());
+      return ResT;
+    }
+    if (PHINode *Phi = dyn_cast<PHINode>(Handle)) {
+      if (Phi->getNumOperands() == 0) {
+        Handle->getContext().emitError("cannot map resource to handle");
+        return HandleMetaMap[Handle];
+      }
+      ResAttribute &Res0 = FindCreateHandleResourceBase(Phi->getOperand(0));
+      // Use Res0 here, ResourceClass, ResourceID match is done at
+      // DxilGenerationPass::AddCreateHandleForPhiNodeAndSelect.
+      HandleMetaMap[Handle] = Res0;
+      for (unsigned i = 1; i < Phi->getNumOperands(); i++) {
+        FindCreateHandleResourceBase(Phi->getOperand(i));
+      }
+      return Res0;
+    }
+    Handle->getContext().emitError("cannot map resource to handle");
+
+    return HandleMetaMap[Handle];
   }
+  CallInst *FindCreateHandle(Value *handle, std::unordered_set<Value *> &resSet) {
+    // Already checked.
+    if (resSet.count(handle))
+      return nullptr;
+    resSet.insert(handle);
+
+    if (CallInst *CI = dyn_cast<CallInst>(handle))
+      return CI;
+    if (SelectInst *Sel = dyn_cast<SelectInst>(handle)) {
+      if (CallInst *CI = FindCreateHandle(Sel->getTrueValue(), resSet))
+          return CI;
+      if (CallInst *CI = FindCreateHandle(Sel->getFalseValue(), resSet))
+          return CI;
+      return nullptr;
+    }
+    if (PHINode *Phi = dyn_cast<PHINode>(handle)) {
+      for (unsigned i = 0; i < Phi->getNumOperands(); i++) {
+        if (CallInst *CI = FindCreateHandle(Phi->getOperand(i), resSet))
+          return CI;
+      }
+      return nullptr;
+    }
 
-  void CollectImmFromPhiChain(Value *resID, std::vector<unsigned> &immResIDs, std::unordered_set<Value *> &resSet) {
+    return nullptr;
+  }
+  void MarkHasCounterOnCreateHandle(Value *handle,
+                                    std::unordered_set<Value *> &resSet) {
     // Already checked.
-    if (resSet.count(resID))
+    if (resSet.count(handle))
       return;
+    resSet.insert(handle);
 
-    resSet.insert(resID);
-
-    if (ConstantInt *constResID = dyn_cast<ConstantInt>(resID)) {
-      immResIDs.emplace_back(constResID->getValue().getLimitedValue());
-    } else {
-      PHINode *phi = cast<PHINode>(resID);
-      for (Use &U : phi->incoming_values()) {
-        Value *V = U.get();
-        CollectImmFromPhiChain(V, immResIDs, resSet);
+    if (CallInst *CI = dyn_cast<CallInst>(handle)) {
+      Value *Res = CI->getArgOperand(HLOperandIndex::kCreateHandleResourceOpIdx);
+      LoadInst *LdRes = dyn_cast<LoadInst>(Res);
+      if (!LdRes) {
+        CI->getContext().emitError(CI, "cannot map resource to handle");
+        return;
       }
+      UpdateCounterSet.insert(LdRes);
+      return;
     }
-  }
-
-  Value *FindHandle(Instruction *I) {
-    if (handleMap.count(I)) {
-      return handleMap[I];
-    } else {
-      I->getContext().emitError(I, "cannot map resource to handle");
-      return nullptr;
+    if (SelectInst *Sel = dyn_cast<SelectInst>(handle)) {
+      MarkHasCounterOnCreateHandle(Sel->getTrueValue(), resSet);
+      MarkHasCounterOnCreateHandle(Sel->getFalseValue(), resSet);
+    }
+    if (PHINode *Phi = dyn_cast<PHINode>(handle)) {
+      for (unsigned i = 0; i < Phi->getNumOperands(); i++) {
+        MarkHasCounterOnCreateHandle(Phi->getOperand(i), resSet);
+      }
     }
-  }
-  void EraseHandle(Instruction *I) {
-    handleMap.erase(I);
   }
 };
 
@@ -283,30 +358,15 @@ Value *TrivialIsSpecialFloat(CallInst *CI, IntrinsicOp IOP, OP::OpCode opcode,
   return TrivialDxilOperation(opcode, args, Ty, RetTy, hlslOP, Builder);
 }
 
-void MarkNonUniformResourceIndex(Instruction *I, hlsl::OP &hlslOP) {
-  for (User *U : I->users()) {
-    if (CallInst *CI = dyn_cast<CallInst>(U)) {
-      if (OP::IsDxilOpFunc(CI->getCalledFunction())) {
-        Value *opArg = CI->getArgOperand(DXIL::OperandIndex::kOpcodeIdx);
-        unsigned opcode = cast<ConstantInt>(opArg)->getLimitedValue();
-        if (opcode == static_cast<unsigned>(DXIL::OpCode::CreateHandle)) {
-          CI->setArgOperand(DXIL::OperandIndex::kCreateHandleIsUniformOpIdx,
-                            hlslOP.GetI1Const(true));
-        }
-      }
-    }
-  }
-}
-
 Value *TranslateNonUniformResourceIndex(CallInst *CI, IntrinsicOp IOP, OP::OpCode opcode,
                       HLOperationLowerHelper &helper,  HLObjectOperationLowerHelper *pObjHelper, bool &Translated) {
-  MarkNonUniformResourceIndex(CI, helper.hlslOP);
   for (User *U : CI->users()) {
     if (CastInst *I = dyn_cast<CastInst>(U)) {
-      MarkNonUniformResourceIndex(I, helper.hlslOP);
+      pObjHelper->MarkNonUniform(I);
     }
   }
   Value *V = CI->getArgOperand(HLOperandIndex::kUnaryOpSrc0Idx);
+  pObjHelper->MarkNonUniform(V);
   CI->replaceAllUsesWith(V);
   return nullptr;
 }
@@ -1835,11 +1895,7 @@ Value *TranslateGetSamplePosition(CallInst *CI, IntrinsicOp IOP, OP::OpCode op,
   hlsl::OP *hlslOP = &helper.hlslOP;
   Instruction *thisArg =
       cast<Instruction>(CI->getArgOperand(HLOperandIndex::kHandleOpIdx));
-  Value *handle = pObjHelper->FindHandle(thisArg);
-  if (!handle) {
-    Translated = false;
-    return nullptr;
-  }
+  Value *handle = thisArg;
 
   IRBuilder<> Builder(CI);
   Value *sampleIdx =
@@ -1868,12 +1924,8 @@ Value *TranslateGetDimensions(CallInst *CI, IntrinsicOp IOP, OP::OpCode op,
   Instruction *thisArg =
       cast<Instruction>(CI->getArgOperand(HLOperandIndex::kHandleOpIdx));
 
-  Value *handle = pObjHelper->FindHandle(thisArg);
-  if (!handle) {
-    Translated = false;
-    return nullptr;
-  }
-  DxilResource::Kind RK = pObjHelper->GetRK(thisArg->getType());
+  Value *handle = thisArg;
+  DxilResource::Kind RK = pObjHelper->GetRK(handle);
 
   IRBuilder<> Builder(CI);
   OP::OpCode opcode = OP::OpCode::GetDimensions;
@@ -1971,11 +2023,7 @@ Value *GenerateUpdateCounter(CallInst *CI, IntrinsicOp IOP, OP::OpCode opcode,
   hlsl::OP *hlslOP = &helper.hlslOP;
   Instruction *thisArg =
       cast<Instruction>(CI->getArgOperand(HLOperandIndex::kHandleOpIdx));
-  Value *handle = pObjHelper->FindHandle(thisArg);
-  if (!handle) {
-    Translated = false;
-    return nullptr;
-  }
+  Value *handle = thisArg;
   pObjHelper->MarkHasCounter(thisArg->getType(), handle);
 
   bool bInc = IOP == IntrinsicOp::MOP_IncrementCounter;
@@ -2118,14 +2166,10 @@ SampleHelper::SampleHelper(
       cast<Instruction>(CI->getArgOperand(kSamplerArgIndex));
 
   IRBuilder<> Builder(CI);
-  texHandle = pObjHelper->FindHandle(texArg);
-  samplerHandle = pObjHelper->FindHandle(samplerArg);
-  if (!texHandle || !samplerHandle) {
-    opcode = DXIL::OpCode::NumOpCodes;
-    return;
-  }
+  texHandle = texArg;
+  samplerHandle = samplerArg;
 
-  DXIL::ResourceKind RK = pObjHelper->GetRK(texArg->getType());
+  DXIL::ResourceKind RK = pObjHelper->GetRK(texHandle);
   unsigned coordDimensions = DxilResource::GetNumCoords(RK);
   unsigned offsetDimensions = DxilResource::GetNumOffsets(RK);
 
@@ -2462,14 +2506,10 @@ GatherHelper::GatherHelper(
   }
 
   IRBuilder<> Builder(CI);
-  texHandle = pObjHelper->FindHandle(texArg);
-  samplerHandle = pObjHelper->FindHandle(samplerArg);
-  if (!texHandle || !samplerHandle) {
-    opcode = DXIL::OpCode::NumOpCodes;
-    return;
-  }
+  texHandle = texArg;
+  samplerHandle = samplerArg;
 
-  DXIL::ResourceKind RK = pObjHelper->GetRK(texArg->getType());
+  DXIL::ResourceKind RK = pObjHelper->GetRK(texHandle);
   unsigned coordSize = DxilResource::GetNumCoords(RK);
   unsigned offsetSize = DxilResource::GetNumOffsets(RK);
 
@@ -2901,16 +2941,11 @@ Value *TranslateResourceLoad(CallInst *CI, IntrinsicOp IOP, OP::OpCode opcode,
   hlsl::OP *hlslOP = &helper.hlslOP;
   Instruction *thisArg =
       cast<Instruction>(CI->getArgOperand(HLOperandIndex::kHandleOpIdx));
-  Value *handle = pObjHelper->FindHandle(thisArg);
-  if (!handle) {
-    Translated = false;
-    return nullptr;
-  }
+  Value *handle = thisArg;
   IRBuilder<> Builder(CI);
 
-  Type *resTy = thisArg->getType();
-  DXIL::ResourceClass RC = pObjHelper->GetRC(resTy);
-  DXIL::ResourceKind RK = pObjHelper->GetRK(resTy);
+  DXIL::ResourceClass RC = pObjHelper->GetRC(handle);
+  DXIL::ResourceKind RK = pObjHelper->GetRK(handle);
 
   ResLoadHelper loadHelper(CI, RK, RC, handle);
   TranslateLoad(loadHelper, RK, Builder, hlslOP, helper.legacyDataLayout);
@@ -3102,13 +3137,9 @@ Value *TranslateResourceStore(CallInst *CI, IntrinsicOp IOP, OP::OpCode opcode,
   hlsl::OP *hlslOP = &helper.hlslOP;
   Instruction *thisArg =
       cast<Instruction>(CI->getArgOperand(HLOperandIndex::kHandleOpIdx));
-  Value *handle = pObjHelper->FindHandle(thisArg);
-  if (!handle) {
-    Translated = false;
-    return nullptr;
-  }
+  Value *handle = thisArg;
   IRBuilder<> Builder(CI);
-  DXIL::ResourceKind RK = pObjHelper->GetRK(thisArg->getType());
+  DXIL::ResourceKind RK = pObjHelper->GetRK(handle);
 
   Value *val = CI->getArgOperand(HLOperandIndex::kStoreValOpIdx);
   Value *offset = CI->getArgOperand(HLOperandIndex::kStoreOffsetOpIdx);
@@ -3224,11 +3255,7 @@ Value *TranslateMopAtomicBinaryOperation(CallInst *CI, IntrinsicOp IOP,
   Instruction *thisArg =
       cast<Instruction>(CI->getArgOperand(HLOperandIndex::kHandleOpIdx));
 
-  Value *handle = pObjHelper->FindHandle(thisArg);
-  if (!handle) {
-    Translated = false;
-    return nullptr;
-  }
+  Value *handle = thisArg;
   IRBuilder<> Builder(CI);
 
   switch (IOP) {
@@ -3329,11 +3356,7 @@ Value *TranslateMopAtomicCmpXChg(CallInst *CI, IntrinsicOp IOP,
   Instruction *thisArg =
       cast<Instruction>(CI->getArgOperand(HLOperandIndex::kHandleOpIdx));
 
-  Value *handle = pObjHelper->FindHandle(thisArg);
-  if (!handle) {
-    Translated = false;
-    return nullptr;
-  }
+  Value *handle = thisArg;
   IRBuilder<> Builder(CI);
   AtomicHelper atomicHelper(CI, OP::OpCode::AtomicCompareExchange, handle);
   TranslateAtomicCmpXChg(atomicHelper, Builder, hlslOP);
@@ -5851,14 +5874,9 @@ void TranslateDefaultSubscript(CallInst *CI, HLOperationLowerHelper &helper,  HL
 
   hlsl::OP *hlslOP = &helper.hlslOP;
   // Resource ptr.
-  Value *handle = pObjHelper->FindHandle(ptrInst);
-  if (!handle) {
-    Translated = false;
-    return;
-  }
-  Type *resTy = ptrInst->getType();
-  DXIL::ResourceClass RC = pObjHelper->GetRC(resTy);
-  DXIL::ResourceKind RK = pObjHelper->GetRK(resTy);
+  Value *handle = ptrInst;
+  DXIL::ResourceClass RC = pObjHelper->GetRC(handle);
+  DXIL::ResourceKind RK = pObjHelper->GetRK(handle);
 
   Type *Ty = CI->getType()->getPointerElementType();
 
@@ -6076,11 +6094,7 @@ void TranslateHLSubscript(CallInst *CI, HLSubscriptOpcode opcode,
   Value *ptr = CI->getArgOperand(HLOperandIndex::kSubscriptObjectOpIdx);
   if (opcode == HLSubscriptOpcode::CBufferSubscript) {
     // Resource ptr.
-    Value *handle = pObjHelper->FindHandle(CI);
-    if (!handle) {
-      Translated = false;
-      return;
-    }
+    Value *handle = CI->getArgOperand(HLOperandIndex::kSubscriptObjectOpIdx);
     if (helper.bLegacyCBufferLoad)
       TranslateCBOperationsLegacy(handle, CI, hlslOP, helper.dxilTypeSys,
                                   helper.legacyDataLayout);
@@ -6089,19 +6103,13 @@ void TranslateHLSubscript(CallInst *CI, HLSubscriptOpcode opcode,
                             hlslOP, helper.dxilTypeSys,
                             CI->getModule()->getDataLayout());
     }
-    // CI will be removed, so erase it from handleMap.
-    pObjHelper->EraseHandle(CI);
     Translated = true;
     return;
   } else if (opcode == HLSubscriptOpcode::DoubleSubscript) {
     Instruction *ptrInst = dyn_cast<Instruction>(ptr);
     // Resource ptr.
-    Value *handle = pObjHelper->FindHandle(ptrInst);
-    if (!handle) {
-      Translated = false;
-      return;
-    }
-    DXIL::ResourceKind RK = pObjHelper->GetRK(ptrInst->getType());
+    Value *handle = ptrInst;
+    DXIL::ResourceKind RK = pObjHelper->GetRK(handle);
     Value *coord = CI->getArgOperand(HLOperandIndex::kSubscriptIndexOpIdx);
     Value *mipLevel =
         CI->getArgOperand(HLOperandIndex::kDoubleSubscriptMipLevelOpIdx);
@@ -6117,16 +6125,17 @@ void TranslateHLSubscript(CallInst *CI, HLSubscriptOpcode opcode,
     Translated = true;
     return;
   } else if (Instruction *ptrInst = dyn_cast<Instruction>(ptr)) {
-    if (HLModule::IsHLSLObjectType(ptrInst->getType())) {
+    Type *HandleTy = hlslOP->GetHandleType();
+    if (ptrInst->getType() == HandleTy) {
       // Resource ptr.
-      Value *handle = pObjHelper->FindHandle(ptrInst);
-      if (!handle) {
+      Value *handle = ptrInst;
+      DXIL::ResourceKind RK = pObjHelper->GetRK(handle);
+      if (RK == DxilResource::Kind::Invalid) {
         Translated = false;
         return;
       }
-      DXIL::ResourceKind RK = pObjHelper->GetRK(ptrInst->getType());
       Translated = true;
-      Type *ObjTy = ptrInst->getType();
+      Type *ObjTy = pObjHelper->GetResourceType(handle);
       Type *RetTy = ObjTy->getStructElementType(0);
       if (RK == DxilResource::Kind::StructuredBuffer) {
         TranslateStructBufSubscript(CI, handle, /*status*/ nullptr, hlslOP,
@@ -6138,6 +6147,9 @@ void TranslateHLSubscript(CallInst *CI, HLSubscriptOpcode opcode,
         // Clear offset for typed buf.
         for (auto User : handle->users()) {
           CallInst *CI = cast<CallInst>(User);
+          // Skip not lowered HL functions.
+          if (hlsl::GetHLOpcodeGroupByName(CI->getCalledFunction()) != HLOpcodeGroup::NotHL)
+            continue;
           switch (hlslOP->GetDxilOpFuncCallInst(CI)) {
           case DXIL::OpCode::BufferLoad: {
             CI->setArgOperand(DXIL::OperandIndex::kBufferLoadCoord1OpIdx,
@@ -6251,7 +6263,6 @@ void TranslateHLBuiltinOperation(Function *F, HLOperationLowerHelper &helper,
 typedef std::unordered_map<llvm::Instruction *, llvm::Value *> HandleMap;
 static void TranslateHLExtension(Function *F,
                                  HLSLExtensionsCodegenHelper *helper,
-                                 const HandleMap &handleMap,
                                  OP& hlslOp) {
   // Find all calls to the function F.
   // Store the calls in a vector for now to be replaced the loop below.
@@ -6266,7 +6277,7 @@ static void TranslateHLExtension(Function *F,
 
   // Get the lowering strategy to use for this intrinsic.
   llvm::StringRef LowerStrategy = GetHLLowerStrategy(F);
-  ExtensionLowering lower(LowerStrategy, helper, handleMap, hlslOp);
+  ExtensionLowering lower(LowerStrategy, helper, hlslOp);
 
   // Replace all calls that were successfully translated.
   for (CallInst *CI : CallsToReplace) {
@@ -6282,27 +6293,34 @@ static void TranslateHLExtension(Function *F,
 namespace hlsl {
 
 void TranslateBuiltinOperations(
-    HLModule &HLM,
-    std::unordered_map<llvm::Instruction *, llvm::Value *> &handleMap,
-    HLSLExtensionsCodegenHelper *extCodegenHelper
-  ) {
+    HLModule &HLM, HLSLExtensionsCodegenHelper *extCodegenHelper,
+    std::unordered_set<LoadInst *> &UpdateCounterSet,
+    std::unordered_set<Value *> &NonUniformSet) {
   HLOperationLowerHelper helper(HLM);
 
-  HLObjectOperationLowerHelper objHelper = {handleMap, HLM};
+  HLObjectOperationLowerHelper objHelper = {HLM, UpdateCounterSet,
+                                            NonUniformSet};
 
   Module *M = HLM.GetModule();
+
   // generate dxil operation
   for (iplist<Function>::iterator F : M->getFunctionList()) {
     if (!F->isDeclaration()) {
       continue;
     }
+    if (F->user_empty())
+      continue;
     hlsl::HLOpcodeGroup group = hlsl::GetHLOpcodeGroup(F);
     if (group == HLOpcodeGroup::NotHL) {
       // Nothing to do.
       continue;
     }
     if (group == HLOpcodeGroup::HLExtIntrinsic) {
-      TranslateHLExtension(F, extCodegenHelper, handleMap, helper.hlslOP);
+      TranslateHLExtension(F, extCodegenHelper, helper.hlslOP);
+      continue;
+    }
+    if (group == HLOpcodeGroup::HLCreateHandle) {
+      // Will lower in later pass.
       continue;
     }
     TranslateHLBuiltinOperation(F, helper, group, &objHelper);

+ 9 - 39
lib/HLSL/HLOperationLowerExtension.cpp

@@ -51,12 +51,12 @@ llvm::StringRef ExtensionLowering::GetStrategyName(Strategy strategy) {
   return "?";
 }
 
-ExtensionLowering::ExtensionLowering(Strategy strategy, HLSLExtensionsCodegenHelper *helper, const HandleMap &handleMap, OP& hlslOp)
-  : m_strategy(strategy), m_helper(helper), m_handleMap(handleMap), m_hlslOp(hlslOp)
+ExtensionLowering::ExtensionLowering(Strategy strategy, HLSLExtensionsCodegenHelper *helper, OP& hlslOp)
+  : m_strategy(strategy), m_helper(helper), m_hlslOp(hlslOp)
   {}
 
-ExtensionLowering::ExtensionLowering(StringRef strategy, HLSLExtensionsCodegenHelper *helper, const HandleMap &handleMap, OP& hlslOp)
-  : ExtensionLowering(GetStrategy(strategy), helper, handleMap, hlslOp)
+ExtensionLowering::ExtensionLowering(StringRef strategy, HLSLExtensionsCodegenHelper *helper, OP& hlslOp)
+  : ExtensionLowering(GetStrategy(strategy), helper, hlslOp)
   {}
 
 llvm::Value *ExtensionLowering::Translate(llvm::CallInst *CI) {
@@ -457,8 +457,7 @@ Value *ExtensionLowering::Pack(CallInst *CI) {
 // Modify a call to a resouce method. Makes the following transformation:
 //
 // 1. Convert non-void return value to dx.types.ResRet.
-// 2. Convert resource parameters to the corresponding dx.types.Handle value.
-// 3. Expand vectors in place as separate arguments.
+// 2. Expand vectors in place as separate arguments.
 //
 // Example
 // -----------------------------------------------------------------------------
@@ -472,10 +471,9 @@ Value *ExtensionLowering::Pack(CallInst *CI) {
 //  %v.2 = insertelement %v.1, %y, 1
 class ResourceMethodCall {
 public:
-  ResourceMethodCall(CallInst *CI, Function &explodedFunction, const ExtensionLowering::HandleMap &handleMap)
+  ResourceMethodCall(CallInst *CI, Function &explodedFunction)
     : m_CI(CI)
     , m_explodedFunction(explodedFunction)
-    , m_handleMap(handleMap)
     , m_builder(CI)
   { }
 
@@ -487,27 +485,10 @@ public:
     return result;
   }
   
-  // Check to see if the value is mapped to a handle in the handleMap.
-  static Instruction *IsResourceHandle(Value *OrigArg, const ExtensionLowering::HandleMap &handleMap) {
-    if (Instruction *Inst = dyn_cast<Instruction>(OrigArg)) {
-      if (handleMap.count(Inst))
-        return Inst;
-    }
-    return nullptr;
-  }
-  
 private:
   CallInst *m_CI;
   Function &m_explodedFunction;
-  const ExtensionLowering::HandleMap &m_handleMap;
   IRBuilder<> m_builder;
-  
-  Value *GetResourceHandle(Value *OrigArg) {
-    if (Instruction *Inst = IsResourceHandle(OrigArg, m_handleMap))
-      return m_handleMap.at(Inst);
-    return nullptr;
-    
-  }
 
   void ExplodeArgs(SmallVectorImpl<Value*> &args) {
     for (Value *arg : m_CI->arg_operands()) {
@@ -518,10 +499,6 @@ private:
           args.push_back(xarg);
         }
       }
-      // resource handle arg: handle -> dx.types.Handle
-      else if (Value *handle = GetResourceHandle(arg)) {
-        args.push_back(handle);
-      }
       // any other value: arg -> arg
       else {
         args.push_back(arg);
@@ -580,10 +557,7 @@ private:
 // Translate function return and argument types for resource method lowering.
 class ResourceFunctionTypeTranslator : public FunctionTypeTranslator {
 public:
-  ResourceFunctionTypeTranslator(const ExtensionLowering::HandleMap &handleMap, OP& hlslOp)
-    : m_handleMap(handleMap)
-    , m_hlslOp(hlslOp)
-  { }
+  ResourceFunctionTypeTranslator(OP &hlslOp) : m_hlslOp(hlslOp) {}
 
   // Translate return type as follows:
   //
@@ -613,25 +587,21 @@ public:
       count = ty->getVectorNumElements();
       ty = ty->getVectorElementType();
     }
-    else if (ResourceMethodCall::IsResourceHandle(OrigArg, m_handleMap)) {
-      ty = m_hlslOp.GetHandleType();
-    }
 
     return ArgumentType(ty, count);
   }
 
 private:
-  const ExtensionLowering::HandleMap &m_handleMap;
   OP& m_hlslOp;
 };
 
 Value *ExtensionLowering::Resource(CallInst *CI) {
-  ResourceFunctionTypeTranslator resourceTypeTranslator(m_handleMap, m_hlslOp);
+  ResourceFunctionTypeTranslator resourceTypeTranslator(m_hlslOp);
   Function *resourceFunction = FunctionTranslator::GetLoweredFunction(resourceTypeTranslator, CI, *this);
   if (!resourceFunction)
     return NoTranslation(CI);
 
-  ResourceMethodCall explode(CI, *resourceFunction, m_handleMap);
+  ResourceMethodCall explode(CI, *resourceFunction);
   Value *result = explode.Generate();
   return result;
 }

+ 16 - 2
lib/HLSL/HLOperations.cpp

@@ -39,6 +39,7 @@ static StringRef HLOpcodeGroupNames[]{
     "subscript",   // HLSubscript,
     "matldst",     // HLMatLoadStore,
     "select",      // HLSelect,
+    "createhandle",// HLCreateHandle,
     "numOfHLDXIL", // NumOfHLOps
 };
 
@@ -53,6 +54,7 @@ static StringRef HLOpcodeGroupFullNames[]{
     "dx.hl.subscript", // HLSubscript,
     "dx.hl.matldst",   // HLMatLoadStore,
     "dx.hl.select",    // HLSelect,
+    "dx.hl.createhandle",  // HLCreateHandle,
     "numOfHLDXIL",     // NumOfHLOps
 };
 
@@ -62,7 +64,12 @@ static HLOpcodeGroup GetHLOpcodeGroupInternal(StringRef group) {
     case 'o': // op
       return HLOpcodeGroup::HLIntrinsic;
     case 'c': // cast
-      return HLOpcodeGroup::HLCast;
+      switch (group[1]) {
+      case 'a': // cast
+        return HLOpcodeGroup::HLCast;
+      case 'r': // createhandle
+        return HLOpcodeGroup::HLCreateHandle;
+      }
     case 'i': // init
       return HLOpcodeGroup::HLInit;
     case 'b': // binaryOp
@@ -83,7 +90,7 @@ static HLOpcodeGroup GetHLOpcodeGroupInternal(StringRef group) {
   return HLOpcodeGroup::NotHL;
 }
 // GetHLOpGroup by function name.
-HLOpcodeGroup GetHLOpcodeGroupByName(Function *F) {
+HLOpcodeGroup GetHLOpcodeGroupByName(const Function *F) {
   StringRef name = F->getName();
 
   if (!name.startswith(HLPrefix)) {
@@ -127,6 +134,7 @@ StringRef GetHLOpcodeGroupName(HLOpcodeGroup op) {
   case HLOpcodeGroup::HLSubscript:
   case HLOpcodeGroup::HLMatLoadStore:
   case HLOpcodeGroup::HLSelect:
+  case HLOpcodeGroup::HLCreateHandle:
     return HLOpcodeGroupNames[static_cast<unsigned>(op)];
   default:
     llvm_unreachable("invalid op");
@@ -144,6 +152,7 @@ StringRef GetHLOpcodeGroupFullName(HLOpcodeGroup op) {
   case HLOpcodeGroup::HLSubscript:
   case HLOpcodeGroup::HLMatLoadStore:
   case HLOpcodeGroup::HLSelect:
+  case HLOpcodeGroup::HLCreateHandle:
     return HLOpcodeGroupFullNames[static_cast<unsigned>(op)];
   default:
     llvm_unreachable("invalid op");
@@ -400,6 +409,11 @@ static void SetHLFunctionAttribute(Function *F, HLOpcodeGroup group,
       if (!F->hasFnAttribute(Attribute::ReadOnly))
         F->addFnAttr(Attribute::ReadOnly);
   } break;
+  case HLOpcodeGroup::HLCreateHandle: {
+    F->addFnAttr(Attribute::ReadNone);
+    F->addFnAttr(Attribute::NoInline);
+    F->setLinkage(llvm::GlobalValue::LinkageTypes::InternalLinkage);
+  } break;
   }
 }
 

+ 2 - 0
lib/Transforms/IPO/PassManagerBuilder.cpp

@@ -212,6 +212,8 @@ static void addHLSLPasses(bool HLSLHighLevel, bool NoOpt, hlsl::HLSLExtensionsCo
   MPM.add(createSimplifyInstPass());
   MPM.add(createCFGSimplificationPass());
 
+  MPM.add(createDxilLegalizeResourceUsePass());
+  MPM.add(createDxilLegalizeStaticResourceUsePass());
   MPM.add(createDxilGenerationPass(NoOpt, ExtHelper));
 
   MPM.add(createSimplifyInstPass());

+ 301 - 178
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -90,6 +90,8 @@ private:
   llvm::DataLayout legacyLayout;
   // decl map to constant id for program
   llvm::DenseMap<HLSLBufferDecl *, uint32_t> constantBufMap;
+  // Map for resource type to resource metadata value.
+  std::unordered_map<llvm::Type *, MDNode*> resMetadataMap;
 
   bool  m_bDebugInfo;
 
@@ -99,6 +101,8 @@ private:
   void AddConstant(VarDecl *constDecl, HLCBuffer &CB);
   uint32_t AddSampler(VarDecl *samplerDecl);
   uint32_t AddUAVSRV(VarDecl *decl, hlsl::DxilResourceBase::Class resClass);
+  bool SetUAVSRV(SourceLocation loc, hlsl::DxilResourceBase::Class resClass,
+                 DxilResource *hlslRes, const RecordDecl *RD);
   uint32_t AddCBuffer(HLSLBufferDecl *D);
   hlsl::DxilResourceBase::Class TypeToClass(clang::QualType Ty);
 
@@ -126,8 +130,6 @@ private:
   void ScanInitList(CodeGenFunction &CGF, InitListExpr *E,
                     SmallVector<Value *, 4> &EltValList,
                     SmallVector<QualType, 4> &EltTyList);
-  // Only scan init list to get the element size;
-  unsigned ScanInitList(InitListExpr *E);
 
   void FlattenAggregatePtrToGepList(CodeGenFunction &CGF, Value *Ptr,
                                     SmallVector<Value *, 4> &idxList,
@@ -949,6 +951,19 @@ static DxilResource::Kind KeywordToKind(StringRef keyword) {
   return DxilResource::Kind::Invalid;
 }
 
+
+static DxilSampler::SamplerKind KeywordToSamplerKind(const std::string &keyword) {
+  // TODO: refactor for faster search (switch by 1/2/3 first letters, then
+  // compare)
+  if (keyword == "SamplerState")
+    return DxilSampler::SamplerKind::Default;
+
+  if (keyword == "SamplerComparisonState")
+    return DxilSampler::SamplerKind::Comparison;
+
+  return DxilSampler::SamplerKind::Invalid;
+}
+
 void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
   // Add hlsl intrinsic attr
   unsigned intrinsicOpcode;
@@ -966,19 +981,46 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
 
       QualType recordTy = MD->getASTContext().getRecordType(RD);
       hlsl::DxilResourceBase::Class resClass = TypeToClass(recordTy);
-
-      llvm::Type *Ty = F->getFunctionType()->params()[0]->getPointerElementType();
-      // Add resource type annotation.
+      llvm::Type *Ty = CGM.getTypes().ConvertType(recordTy);
+      llvm::FunctionType *FT = F->getFunctionType();
+      // Save resource type metadata.
       switch (resClass) {
-      case DXIL::ResourceClass::Sampler:
-        m_pHLModule->AddResourceTypeAnnotation(Ty, DXIL::ResourceClass::Sampler,
-                                               DXIL::ResourceKind::Sampler);
-        break;
-      case DXIL::ResourceClass::UAV:
+      case DXIL::ResourceClass::UAV: {
+        DxilResource UAV;
+        // TODO: save globalcoherent to variable in EmitHLSLBuiltinCallExpr.
+        SetUAVSRV(FD->getLocation(), resClass, &UAV, RD);
+        // Set global symbol to save type.
+        UAV.SetGlobalSymbol(UndefValue::get(Ty));
+        MDNode * MD = m_pHLModule->DxilUAVToMDNode(UAV);
+        resMetadataMap[Ty] = MD;
+      } break;
       case DXIL::ResourceClass::SRV: {
-        hlsl::DxilResource::Kind kind = KeywordToKind(RD->getName());
-        m_pHLModule->AddResourceTypeAnnotation(Ty, resClass, kind);
+        DxilResource SRV;
+        SetUAVSRV(FD->getLocation(), resClass, &SRV, RD);
+        // Set global symbol to save type.
+        SRV.SetGlobalSymbol(UndefValue::get(Ty));
+        MDNode * Meta = m_pHLModule->DxilSRVToMDNode(SRV);
+        resMetadataMap[Ty] = Meta;
+        if (FT->getNumParams() > 1) {
+          QualType paramTy = MD->getParamDecl(0)->getType();
+          // Add sampler type.
+          if (TypeToClass(paramTy) == DXIL::ResourceClass::Sampler) {
+            llvm::Type * Ty = FT->getParamType(1)->getPointerElementType();
+            DxilSampler S;
+            const RecordType *RT = paramTy->getAs<RecordType>();
+            DxilSampler::SamplerKind kind =
+                KeywordToSamplerKind(RT->getDecl()->getName());
+            S.SetSamplerKind(kind);
+            // Set global symbol to save type.
+            S.SetGlobalSymbol(UndefValue::get(Ty));
+            MDNode *MD = m_pHLModule->DxilSamplerToMDNode(S);
+            resMetadataMap[Ty] = MD;
+          }
+        }
       } break;
+      default:
+        // Skip OutputStream for GS.
+        break;
       }
     }
 
@@ -1827,17 +1869,7 @@ static DxilResourceBase::Class KeywordToClass(const std::string &keyword) {
 
   return DxilResourceBase::Class::Invalid;
 }
-static DxilSampler::SamplerKind KeywordToSamplerKind(const std::string &keyword) {
-  // TODO: refactor for faster search (switch by 1/2/3 first letters, then
-  // compare)
-  if (keyword == "SamplerState")
-    return DxilSampler::SamplerKind::Default;
-
-  if (keyword == "SamplerComparisonState")
-    return DxilSampler::SamplerKind::Comparison;
 
-  return DxilSampler::SamplerKind::Invalid;
-}
 // This should probably be refactored to ASTContextHLSL, and follow types
 // rather than do string comparisons.
 DXIL::ResourceClass
@@ -1987,62 +2019,10 @@ static void CollectScalarTypes(std::vector<QualType> &ScalarTys, QualType Ty) {
   }
 }
 
-uint32_t CGMSHLSLRuntime::AddUAVSRV(VarDecl *decl,
-                                    hlsl::DxilResourceBase::Class resClass) {
-  llvm::GlobalVariable *val =
-      cast<llvm::GlobalVariable>(CGM.GetAddrOfGlobalVar(decl));
-
-  QualType VarTy = decl->getType().getCanonicalType();
-
-  unique_ptr<HLResource> hlslRes(new HLResource);
-  hlslRes->SetLowerBound(UINT_MAX);
-  hlslRes->SetGlobalSymbol(val);
-  hlslRes->SetGlobalName(decl->getName());
-  if (const clang::ArrayType *arrayType =
-          CGM.getContext().getAsArrayType(VarTy)) {
-    if (arrayType->isConstantArrayType()) {
-      uint32_t arraySize =
-          cast<ConstantArrayType>(arrayType)->getSize().getLimitedValue();
-      hlslRes->SetRangeSize(arraySize);
-    } else
-      hlslRes->SetRangeSize(UINT_MAX);
-    // use elementTy
-    VarTy = arrayType->getElementType();
-    // Support more dim.
-    while (const clang::ArrayType *arrayType =
-               CGM.getContext().getAsArrayType(VarTy)) {
-      unsigned rangeSize = hlslRes->GetRangeSize();
-      if (arrayType->isConstantArrayType()) {
-        uint32_t arraySize =
-            cast<ConstantArrayType>(arrayType)->getSize().getLimitedValue();
-        if (rangeSize != UINT_MAX)
-          hlslRes->SetRangeSize(rangeSize * arraySize);
-      } else
-        hlslRes->SetRangeSize(UINT_MAX);
-      // use elementTy
-      VarTy = arrayType->getElementType();
-    }
-  } else
-    hlslRes->SetRangeSize(1);
-
-  for (hlsl::UnusualAnnotation *it : decl->getUnusualAnnotations()) {
-    switch (it->getKind()) {
-    case hlsl::UnusualAnnotation::UA_RegisterAssignment: {
-      hlsl::RegisterAssignment *ra = cast<hlsl::RegisterAssignment>(it);
-      hlslRes->SetLowerBound(ra->RegisterNumber);
-      hlslRes->SetSpaceID(ra->RegisterSpace);
-      break;
-    }
-    default:
-      llvm_unreachable("only register for uav/srv");
-      break;
-    }
-  }
-
-  const RecordType *RT = VarTy->getAs<RecordType>();
-  RecordDecl *RD = RT->getDecl();
-
-  hlsl::DxilResource::Kind kind = KeywordToKind(RT->getDecl()->getName());
+bool CGMSHLSLRuntime::SetUAVSRV(SourceLocation loc,
+                                hlsl::DxilResourceBase::Class resClass,
+                                DxilResource *hlslRes, const RecordDecl *RD) {
+  hlsl::DxilResource::Kind kind = KeywordToKind(RD->getName());
   hlslRes->SetKind(kind);
 
   // Get the result type from handle field.
@@ -2052,12 +2032,12 @@ uint32_t CGMSHLSLRuntime::AddUAVSRV(VarDecl *decl,
   // Type annotation for result type of resource.
   DxilTypeSystem &dxilTypeSys = m_pHLModule->GetTypeSystem();
   unsigned arrayEltSize = 0;
-  AddTypeAnnotation(decl->getType(), dxilTypeSys, arrayEltSize);
+  AddTypeAnnotation(QualType(RD->getTypeForDecl(),0), dxilTypeSys, arrayEltSize);
 
   if (kind == hlsl::DxilResource::Kind::Texture2DMS ||
       kind == hlsl::DxilResource::Kind::Texture2DMSArray) {
     const ClassTemplateSpecializationDecl *templateDecl =
-        dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+        dyn_cast<ClassTemplateSpecializationDecl>(RD);
     const clang::TemplateArgument &sampleCountArg =
         templateDecl->getTemplateArgs()[1];
     uint32_t sampleCount = sampleCountArg.getAsIntegral().getLimitedValue();
@@ -2079,17 +2059,18 @@ uint32_t CGMSHLSLRuntime::AddUAVSRV(VarDecl *decl,
       if (size == 0) {
         DiagnosticsEngine &Diags = CGM.getDiags();
         unsigned DiagID = Diags.getCustomDiagID(
-            DiagnosticsEngine::Error, "object's templated type must have at least one element");
-        Diags.Report(decl->getLocation(), DiagID);
-        return 0;
+            DiagnosticsEngine::Error,
+            "object's templated type must have at least one element");
+        Diags.Report(loc, DiagID);
+        return false;
       }
       if (size > 4) {
         DiagnosticsEngine &Diags = CGM.getDiags();
         unsigned DiagID = Diags.getCustomDiagID(
             DiagnosticsEngine::Error, "elements of typed buffers and textures "
                                       "must fit in four 32-bit quantities");
-        Diags.Report(decl->getLocation(), DiagID);
-        return 0;
+        Diags.Report(loc, DiagID);
+        return false;
       }
 
       EltTy = ScalarTys[0];
@@ -2099,8 +2080,8 @@ uint32_t CGMSHLSLRuntime::AddUAVSRV(VarDecl *decl,
           unsigned DiagID = Diags.getCustomDiagID(
               DiagnosticsEngine::Error,
               "all template type components must have the same type");
-          Diags.Report(decl->getLocation(), DiagID);
-          return 0;
+          Diags.Report(loc, DiagID);
+          return false;
         }
       }
     }
@@ -2127,11 +2108,9 @@ uint32_t CGMSHLSLRuntime::AddUAVSRV(VarDecl *decl,
       const BuiltinType *BTy = EltTy->getAs<BuiltinType>();
       CompType::Kind kind = BuiltinTyToCompTy(BTy, bSNorm, bUNorm);
       // 64bits types are implemented with u32.
-      if (kind == CompType::Kind::U64 ||
-          kind == CompType::Kind::I64 ||
+      if (kind == CompType::Kind::U64 || kind == CompType::Kind::I64 ||
           kind == CompType::Kind::SNormF64 ||
-          kind == CompType::Kind::UNormF64 ||
-          kind == CompType::Kind::F64) {
+          kind == CompType::Kind::UNormF64 || kind == CompType::Kind::F64) {
         kind = CompType::Kind::U32;
       }
       hlslRes->SetCompType(kind);
@@ -2140,16 +2119,12 @@ uint32_t CGMSHLSLRuntime::AddUAVSRV(VarDecl *decl,
     }
   }
 
-  if (decl->hasAttr<HLSLGloballyCoherentAttr>()) {
-    hlslRes->SetGloballyCoherent(true);
-  }
-
-  hlslRes->SetROV(RT->getDecl()->getName().startswith("RasterizerOrdered"));
+  hlslRes->SetROV(RD->getName().startswith("RasterizerOrdered"));
 
   if (kind == hlsl::DxilResource::Kind::TypedBuffer ||
       kind == hlsl::DxilResource::Kind::StructuredBuffer) {
     const ClassTemplateSpecializationDecl *templateDecl =
-        dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+        dyn_cast<ClassTemplateSpecializationDecl>(RD);
 
     const clang::TemplateArgument &retTyArg =
         templateDecl->getTemplateArgs()[0];
@@ -2165,15 +2140,84 @@ uint32_t CGMSHLSLRuntime::AddUAVSRV(VarDecl *decl,
       unsigned DiagID = Diags.getCustomDiagID(
           DiagnosticsEngine::Error, "globallycoherent can only be used with "
                                     "Unordered Access View buffers.");
-      Diags.Report(decl->getLocation(), DiagID);
+      Diags.Report(loc, DiagID);
+      return false;
     }
 
     hlslRes->SetRW(false);
     hlslRes->SetID(m_pHLModule->GetSRVs().size());
-    return m_pHLModule->AddSRV(std::move(hlslRes));
   } else {
     hlslRes->SetRW(true);
     hlslRes->SetID(m_pHLModule->GetUAVs().size());
+  }
+  return true;
+}
+
+uint32_t CGMSHLSLRuntime::AddUAVSRV(VarDecl *decl,
+                                    hlsl::DxilResourceBase::Class resClass) {
+  llvm::GlobalVariable *val =
+      cast<llvm::GlobalVariable>(CGM.GetAddrOfGlobalVar(decl));
+
+  QualType VarTy = decl->getType().getCanonicalType();
+
+  unique_ptr<HLResource> hlslRes(new HLResource);
+  hlslRes->SetLowerBound(UINT_MAX);
+  hlslRes->SetGlobalSymbol(val);
+  hlslRes->SetGlobalName(decl->getName());
+  if (const clang::ArrayType *arrayType =
+          CGM.getContext().getAsArrayType(VarTy)) {
+    if (arrayType->isConstantArrayType()) {
+      uint32_t arraySize =
+          cast<ConstantArrayType>(arrayType)->getSize().getLimitedValue();
+      hlslRes->SetRangeSize(arraySize);
+    } else
+      hlslRes->SetRangeSize(UINT_MAX);
+    // use elementTy
+    VarTy = arrayType->getElementType();
+    // Support more dim.
+    while (const clang::ArrayType *arrayType =
+               CGM.getContext().getAsArrayType(VarTy)) {
+      unsigned rangeSize = hlslRes->GetRangeSize();
+      if (arrayType->isConstantArrayType()) {
+        uint32_t arraySize =
+            cast<ConstantArrayType>(arrayType)->getSize().getLimitedValue();
+        if (rangeSize != UINT_MAX)
+          hlslRes->SetRangeSize(rangeSize * arraySize);
+      } else
+        hlslRes->SetRangeSize(UINT_MAX);
+      // use elementTy
+      VarTy = arrayType->getElementType();
+    }
+  } else
+    hlslRes->SetRangeSize(1);
+
+  for (hlsl::UnusualAnnotation *it : decl->getUnusualAnnotations()) {
+    switch (it->getKind()) {
+    case hlsl::UnusualAnnotation::UA_RegisterAssignment: {
+      hlsl::RegisterAssignment *ra = cast<hlsl::RegisterAssignment>(it);
+      hlslRes->SetLowerBound(ra->RegisterNumber);
+      hlslRes->SetSpaceID(ra->RegisterSpace);
+      break;
+    }
+    default:
+      llvm_unreachable("only register for uav/srv");
+      break;
+    }
+  }
+
+  const RecordType *RT = VarTy->getAs<RecordType>();
+  RecordDecl *RD = RT->getDecl();
+
+  if (decl->hasAttr<HLSLGloballyCoherentAttr>()) {
+    hlslRes->SetGloballyCoherent(true);
+  }
+
+  if (!SetUAVSRV(decl->getLocation(), resClass, hlslRes.get(), RD))
+    return 0;
+
+  if (resClass == hlsl::DxilResourceBase::Class::SRV) {
+    return m_pHLModule->AddSRV(std::move(hlslRes));
+  } else {
     return m_pHLModule->AddUAV(std::move(hlslRes));
   }
 }
@@ -2223,6 +2267,7 @@ void CGMSHLSLRuntime::AddConstant(VarDecl *constDecl, HLCBuffer &CB) {
   }
 
   llvm::Constant *constVal = CGM.GetAddrOfGlobalVar(constDecl);
+
   bool isGlobalCB = CB.GetID() == globalCBIndex;
   uint32_t offset = 0;
   bool userOffset = false;
@@ -2524,8 +2569,33 @@ void MarkUsedFunctionForConst(Value *V, std::unordered_set<Function*> &usedFunc)
   }
 }
 
+static Function * GetOrCreateHLCreateHandle(HLModule &HLM, llvm::Type *HandleTy,
+    ArrayRef<Value*> paramList, MDNode *MD) {
+  SmallVector<llvm::Type *, 4> paramTyList;
+  for (Value *param : paramList) {
+    paramTyList.emplace_back(param->getType());
+  }
+
+  llvm::FunctionType *funcTy =
+      llvm::FunctionType::get(HandleTy, paramTyList, false);
+  llvm::Module &M = *HLM.GetModule();
+  Function *CreateHandle = GetOrCreateHLFunctionWithBody(M, funcTy, HLOpcodeGroup::HLCreateHandle,
+      /*opcode*/ 0, "");
+  if (CreateHandle->empty()) {
+    // Add body.
+    BasicBlock *BB =
+        BasicBlock::Create(CreateHandle->getContext(), "Entry", CreateHandle);
+    IRBuilder<> Builder(BB);
+    // Just return undef to make a body.
+    Builder.CreateRet(UndefValue::get(HandleTy));
+    // Mark resource attribute.
+    HLM.MarkDxilResourceAttrib(CreateHandle, MD);
+  }
+  return CreateHandle;
+}
+
 static bool CreateCBufferVariable(HLCBuffer &CB,
-    llvm::Module &M) {
+    HLModule &HLM, llvm::Type *HandleTy) {
   bool bUsed = false;
   // Build Struct for CBuffer.
   SmallVector<llvm::Type*, 4> Elements;
@@ -2541,6 +2611,8 @@ static bool CreateCBufferVariable(HLCBuffer &CB,
   if (!bUsed)
     return false;
 
+  llvm::Module &M = *HLM.GetModule();
+
   bool isCBArray = CB.GetRangeSize() != 1;
   llvm::GlobalVariable *cbGV = nullptr;
   llvm::Type *cbTy = nullptr;
@@ -2585,14 +2657,20 @@ static bool CreateCBufferVariable(HLCBuffer &CB,
 
   llvm::Type *opcodeTy = llvm::Type::getInt32Ty(M.getContext());
   llvm::Type *idxTy = opcodeTy;
+  Constant *zeroIdx = ConstantInt::get(opcodeTy, 0);
+
+  MDNode *MD = HLM.DxilCBufferToMDNode(CB);
+
+  Value *HandleArgs[] = { zeroIdx, cbGV, zeroIdx };
+  Function *CreateHandleFunc = GetOrCreateHLCreateHandle(HLM, HandleTy, HandleArgs, MD);
+
   llvm::FunctionType *SubscriptFuncTy =
-      llvm::FunctionType::get(cbTy, { opcodeTy, cbGV->getType(), idxTy}, false);
+      llvm::FunctionType::get(cbTy, { opcodeTy, HandleTy, idxTy}, false);
 
   Function *subscriptFunc =
       GetOrCreateHLFunction(M, SubscriptFuncTy, HLOpcodeGroup::HLSubscript,
                             (unsigned)HLSubscriptOpcode::CBufferSubscript);
   Constant *opArg = ConstantInt::get(opcodeTy, (unsigned)HLSubscriptOpcode::CBufferSubscript);
-  Constant *zeroIdx = ConstantInt::get(opcodeTy, 0);
   Value *args[] = { opArg, nullptr, zeroIdx };
 
   llvm::LLVMContext &Context = M.getContext();
@@ -2611,83 +2689,99 @@ static bool CreateCBufferVariable(HLCBuffer &CB,
   }
 
   for (Function &F : M.functions()) {
-    if (!F.isDeclaration()) {
-      IRBuilder<> Builder(F.getEntryBlock().getFirstInsertionPt());
+    if (F.isDeclaration())
+      continue;
 
-      args[HLOperandIndex::kSubscriptObjectOpIdx] = cbGV;
-      // create HL subscript to make all the use of cbuffer start from it.
-      Instruction *cbSubscript = cast<Instruction>(Builder.CreateCall(subscriptFunc, {args} ));
+    if (GetHLOpcodeGroupByName(&F) != HLOpcodeGroup::NotHL)
+      continue;
 
-      // Replace constant var with GEP pGV
-      for (const std::unique_ptr<DxilResourceBase> &C : CB.GetConstants()) {
-        Value *GV = C->GetGlobalSymbol();
-        if (constUsedFuncList[C->GetID()].count(&F) == 0)
-          continue;
+    IRBuilder<> Builder(F.getEntryBlock().getFirstInsertionPt());
 
-        Value *idx = indexArray[C->GetID()];
-        if (!isCBArray) {
-          Instruction *GEP = cast<Instruction>(
-              Builder.CreateInBoundsGEP(cbSubscript, {zero, idx}));
-          // TODO: make sure the debug info is synced to GEP.
-          // GEP->setDebugLoc(GV);
-          ReplaceUseInFunction(GV, GEP, &F, Builder);
-          // Delete if no use in F.
-          if (GEP->user_empty())
-            GEP->eraseFromParent();
-        } else {
-          for (auto U = GV->user_begin(); U != GV->user_end();) {
-            User *user = *(U++);
-            if (user->user_empty())
-              continue;
-            Instruction *I = dyn_cast<Instruction>(user);
-            if (I && I->getParent()->getParent() != &F)
-              continue;
+    // create HL subscript to make all the use of cbuffer start from it.
+    HandleArgs[HLOperandIndex::kCreateHandleResourceOpIdx] = cbGV;
+    CallInst *Handle = Builder.CreateCall(CreateHandleFunc, HandleArgs);
+    args[HLOperandIndex::kSubscriptObjectOpIdx] = Handle;
+    Instruction *cbSubscript =
+        cast<Instruction>(Builder.CreateCall(subscriptFunc, {args}));
 
-            IRBuilder<> *instBuilder = &Builder;
-            unique_ptr<IRBuilder<> > B;
-            if (I) {
-              B = make_unique<IRBuilder<> >(I);
-              instBuilder = B.get();
-            }
+    // Replace constant var with GEP pGV
+    for (const std::unique_ptr<DxilResourceBase> &C : CB.GetConstants()) {
+      Value *GV = C->GetGlobalSymbol();
+      if (constUsedFuncList[C->GetID()].count(&F) == 0)
+        continue;
 
-            GEPOperator *GEPOp = cast<GEPOperator>(user);
-            std::vector<Value *> idxList;
+      Value *idx = indexArray[C->GetID()];
+      if (!isCBArray) {
+        Instruction *GEP = cast<Instruction>(
+            Builder.CreateInBoundsGEP(cbSubscript, {zero, idx}));
+        // TODO: make sure the debug info is synced to GEP.
+        // GEP->setDebugLoc(GV);
+        ReplaceUseInFunction(GV, GEP, &F, Builder);
+        // Delete if no use in F.
+        if (GEP->user_empty())
+          GEP->eraseFromParent();
+      } else {
+        for (auto U = GV->user_begin(); U != GV->user_end();) {
+          User *user = *(U++);
+          if (user->user_empty())
+            continue;
+          Instruction *I = dyn_cast<Instruction>(user);
+          if (I && I->getParent()->getParent() != &F)
+            continue;
 
-            DXASSERT(GEPOp->getNumIndices() >= 1 + cbIndexDepth,
-                        "must indexing ConstantBuffer array");
-            idxList.reserve(GEPOp->getNumIndices() - (cbIndexDepth - 1));
+          IRBuilder<> *instBuilder = &Builder;
+          unique_ptr<IRBuilder<>> B;
+          if (I) {
+            B = make_unique<IRBuilder<>>(I);
+            instBuilder = B.get();
+          }
 
-            gep_type_iterator GI = gep_type_begin(*GEPOp), E = gep_type_end(*GEPOp);
-            idxList.push_back(GI.getOperand());
-            // change array index with 0 for struct index.
-            idxList.push_back(zero);
-            GI++;
-            Value *arrayIdx = GI.getOperand();
-            GI++;
-            for (unsigned curIndex = 1; GI != E && curIndex < cbIndexDepth; ++GI, ++curIndex) {
-              arrayIdx = instBuilder->CreateMul(arrayIdx, Builder.getInt32(GI->getArrayNumElements()));
-              arrayIdx = instBuilder->CreateAdd(arrayIdx, GI.getOperand());
-            }
+          GEPOperator *GEPOp = cast<GEPOperator>(user);
+          std::vector<Value *> idxList;
+
+          DXASSERT(GEPOp->getNumIndices() >= 1 + cbIndexDepth,
+                   "must indexing ConstantBuffer array");
+          idxList.reserve(GEPOp->getNumIndices() - (cbIndexDepth - 1));
+
+          gep_type_iterator GI = gep_type_begin(*GEPOp),
+                            E = gep_type_end(*GEPOp);
+          idxList.push_back(GI.getOperand());
+          // change array index with 0 for struct index.
+          idxList.push_back(zero);
+          GI++;
+          Value *arrayIdx = GI.getOperand();
+          GI++;
+          for (unsigned curIndex = 1; GI != E && curIndex < cbIndexDepth;
+               ++GI, ++curIndex) {
+            arrayIdx = instBuilder->CreateMul(
+                arrayIdx, Builder.getInt32(GI->getArrayNumElements()));
+            arrayIdx = instBuilder->CreateAdd(arrayIdx, GI.getOperand());
+          }
 
-            for (; GI != E; ++GI) {
-              idxList.push_back(GI.getOperand());
-            }
+          for (; GI != E; ++GI) {
+            idxList.push_back(GI.getOperand());
+          }
 
-            args[HLOperandIndex::kSubscriptIndexOpIdx] = arrayIdx;
+          HandleArgs[HLOperandIndex::kCreateHandleIndexOpIdx] = arrayIdx;
+          CallInst *Handle =
+              instBuilder->CreateCall(CreateHandleFunc, HandleArgs);
+          args[HLOperandIndex::kSubscriptObjectOpIdx] = Handle;
+          args[HLOperandIndex::kSubscriptIndexOpIdx] = arrayIdx;
 
-            Instruction *cbSubscript =
-                cast<Instruction>(instBuilder->CreateCall(subscriptFunc, {args}));
+          Instruction *cbSubscript =
+              cast<Instruction>(instBuilder->CreateCall(subscriptFunc, {args}));
 
-            Instruction *NewGEP = cast<Instruction>(
-                instBuilder->CreateInBoundsGEP(cbSubscript, idxList));
+          Instruction *NewGEP = cast<Instruction>(
+              instBuilder->CreateInBoundsGEP(cbSubscript, idxList));
 
-            ReplaceUseInFunction(GEPOp, NewGEP, &F, *instBuilder);
-          }
+          ReplaceUseInFunction(GEPOp, NewGEP, &F, *instBuilder);
         }
       }
-      // Delete if no use in F.
-      if (cbSubscript->user_empty())
-        cbSubscript->eraseFromParent();
+    }
+    // Delete if no use in F.
+    if (cbSubscript->user_empty()) {
+      cbSubscript->eraseFromParent();
+      Handle->eraseFromParent();
     }
   }
   return true;
@@ -2729,6 +2823,7 @@ static void ConstructCBuffer(
     llvm::Type *CBufferType,
     std::unordered_map<Constant *, DxilFieldAnnotation> &AnnotationMap) {
   DxilTypeSystem &dxilTypeSys = pHLModule->GetTypeSystem();
+  llvm::Type *HandleTy = pHLModule->GetOP()->GetHandleType();
   for (unsigned i = 0; i < pHLModule->GetCBuffers().size(); i++) {
     HLCBuffer &CB = *static_cast<HLCBuffer*>(&(pHLModule->GetCBuffer(i)));
     if (CB.GetConstants().size() == 0) {
@@ -2738,7 +2833,8 @@ static void ConstructCBuffer(
           llvm::GlobalValue::ExternalLinkage, nullptr, CB.GetGlobalName());
       CB.SetGlobalSymbol(pGV);
     } else {
-      bool bCreated = CreateCBufferVariable(CB, *pHLModule->GetModule());
+      bool bCreated =
+          CreateCBufferVariable(CB, *pHLModule, HandleTy);
       if (bCreated)
         ConstructCBufferAnnotation(CB, dxilTypeSys, AnnotationMap);
       else {
@@ -2932,8 +3028,26 @@ static Function *CreateOpFunction(llvm::Module &M, Function *F,
   return opFunc;
 }
 
+static Value *CreateHandleFromResPtr(
+    Value *ResPtr, HLModule &HLM, llvm::Type *HandleTy,
+    std::unordered_map<llvm::Type *, MDNode *> &resMetaMap,
+    IRBuilder<> &Builder) {
+  llvm::Type *objTy = ResPtr->getType()->getPointerElementType();
+  DXASSERT(resMetaMap.count(objTy), "cannot find resource type");
+  MDNode *MD = resMetaMap[objTy];
+  // Load to make sure resource only have Ld/St use so mem2reg could remove
+  // temp resource.
+  Value *ldObj = Builder.CreateLoad(ResPtr);
+  Value *opcode = Builder.getInt32(0);
+  Value *args[] = {opcode, ldObj};
+  Function *CreateHandle = GetOrCreateHLCreateHandle(HLM, HandleTy, args, MD);
+  CallInst *Handle = Builder.CreateCall(CreateHandle, args);
+  return Handle;
+}
+
 static void AddOpcodeParamForIntrinsic(HLModule &HLM, Function *F,
-                                       unsigned opcode) {
+                                       unsigned opcode, llvm::Type *HandleTy,
+    std::unordered_map<llvm::Type *, MDNode*> &resMetaMap) {
   llvm::Module &M = *HLM.GetModule();
   llvm::FunctionType *oldFuncTy = F->getFunctionType();
 
@@ -2950,9 +3064,9 @@ static void AddOpcodeParamForIntrinsic(HLModule &HLM, Function *F,
       if (HLModule::IsHLSLObjectType(Ty) &&
           // StreamOutput don't need handle.
           !HLModule::IsStreamOutputType(Ty)) {
-        // Use object type directly, not by pointer.
-        // This will make sure temp object variable only used by ld/st.
-        paramTyList[i] = Ty;
+        // Use handle type for object type.
+        // This will make sure temp object variable only used by createHandle.
+        paramTyList[i] = HandleTy;
       }
     }
   }
@@ -3016,8 +3130,8 @@ static void AddOpcodeParamForIntrinsic(HLModule &HLM, Function *F,
     }
 
     DXASSERT(resTy, "must find the resource type");
-    // Change object type to resource type.
-    paramTyList[HLOperandIndex::kSubscriptObjectOpIdx] = resTy;
+    // Change object type to handle type.
+    paramTyList[HLOperandIndex::kSubscriptObjectOpIdx] = HandleTy;
     // Change RetTy into pointer of resource reture type.
     RetTy = cast<StructType>(resTy)->getElementType(0)->getPointerTo();
 
@@ -3061,8 +3175,11 @@ static void AddOpcodeParamForIntrinsic(HLModule &HLM, Function *F,
       objVal = objGEP->getPointerOperand();
       if (IndexList.size() > 1)
         objVal = Builder.CreateInBoundsGEP(objVal, IndexList);
+
+      Value *Handle =
+          CreateHandleFromResPtr(objVal, HLM, HandleTy, resMetaMap, Builder);
       // Change obj to the resource pointer.
-      opcodeParamList[HLOperandIndex::kSubscriptObjectOpIdx] = objVal;
+      opcodeParamList[HLOperandIndex::kSubscriptObjectOpIdx] = Handle;
 
       // Set idx and mipIdx.
       Value *mipIdx = opcodeParamList[HLOperandIndex::kSubscriptIndexOpIdx];
@@ -3101,7 +3218,9 @@ static void AddOpcodeParamForIntrinsic(HLModule &HLM, Function *F,
             Builder.Insert(GEP);
             arg = GEP;
           }
-          opcodeParamList[i] = Builder.CreateLoad(arg);
+          Value *Handle = CreateHandleFromResPtr(arg, HLM, HandleTy,
+                                                 resMetaMap, Builder);
+          opcodeParamList[i] = Handle;
         }
       }
     }
@@ -3127,7 +3246,9 @@ static void AddOpcodeParamForIntrinsic(HLModule &HLM, Function *F,
 }
 
 static void AddOpcodeParamForIntrinsics(HLModule &HLM
-    , std::vector<std::pair<Function *, unsigned>> &intrinsicMap) {
+    , std::vector<std::pair<Function *, unsigned>> &intrinsicMap,
+    std::unordered_map<llvm::Type *, MDNode*> &resMetaMap) {
+  llvm::Type *HandleTy = HLM.GetOP()->GetHandleType();
   for (auto mapIter : intrinsicMap) {
     Function *F = mapIter.first;
     if (F->user_empty()) {
@@ -3137,7 +3258,7 @@ static void AddOpcodeParamForIntrinsics(HLModule &HLM
     }
 
     unsigned opcode = mapIter.second;
-    AddOpcodeParamForIntrinsic(HLM, F, opcode);
+    AddOpcodeParamForIntrinsic(HLM, F, opcode, HandleTy, resMetaMap);
   }
 }
 
@@ -3769,7 +3890,7 @@ void CGMSHLSLRuntime::FinishCodeGen() {
                 EntryFunc->getEntryBlock().getFirstInsertionPt());
 
   // translate opcode into parameter for intrinsic functions
-  AddOpcodeParamForIntrinsics(*m_pHLModule, m_IntrinsicMap);
+  AddOpcodeParamForIntrinsics(*m_pHLModule, m_IntrinsicMap, resMetadataMap);
 
   // Pin entry point and constant buffers, mark everything else internal.
   for (Function &f : m_pHLModule->GetModule()->functions()) {
@@ -3779,7 +3900,9 @@ void CGMSHLSLRuntime::FinishCodeGen() {
     } else {
       f.setLinkage(GlobalValue::LinkageTypes::InternalLinkage);
     }
-
+    // Skip no inline functions.
+    if (f.hasFnAttribute(llvm::Attribute::NoInline))
+      continue;
     // Always inline.
     f.addFnAttr(llvm::Attribute::AlwaysInline);
   }

+ 5 - 4
tools/clang/test/CodeGenHLSL/bindings1.hlsl

@@ -93,6 +93,11 @@
 // CHECK: ; RWTex1                                UAV     f32          2d      U3             u0     4
 
 // CHECK: %struct.Resources = type { %class.Texture2D, %class.Texture2D.0, %class.Texture2D, %class.Texture2D.0, %class.RWTexture2D, %class.RWTexture2D, %class.RWTexture2D, %class.RWTexture2D, %struct.SamplerComparisonState, %struct.SamplerState, %struct.SamplerComparisonState, %struct.SamplerState, <4 x float> }
+
+// CHECK: %RWTex2_UAV_2d = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 7, i1 false)
+// CHECK: %Tex1_texture_2d = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false)
+// CHECK: %Samp2_sampler = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false)
+
 // CHECK: %tbuf4_buffer = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 8, i32 4, i1 false)
 // CHECK: %tbuf2_buffer = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 7, i32 2, i1 false)
 // CHECK: %tbuf3_buffer = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 6, i32 6, i1 false)
@@ -104,10 +109,6 @@
 // CHECK: %MyCB_buffer = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 11, i1 false)
 // CHECK: %MyTB_buffer = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 4, i32 11, i1 false)
 
-// CHECK: %RWTex2_UAV_2d = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 7, i1 false)
-// CHECK: %Tex1_texture_2d = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false)
-// CHECK: %Samp2_sampler = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false)
-
 // CHECK: %Tex2_texture_2d = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 1, i32 30, i1 false)
 // CHECK: %Tex3_texture_2d = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 2, i32 94, i1 false)
 // CHECK: %Tex4_texture_2d = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 3, i32 10, i1 false)

+ 2 - 0
utils/hct/hctdb.py

@@ -1208,6 +1208,8 @@ class db_dxil(object):
         add_pass('globaldce', 'GlobalDCE', 'Dead Global Elimination', [])
         add_pass('dynamic-vector-to-array', 'DynamicIndexingVectorToArray', 'Replace dynamic indexing vector with array', [
             {'n':'ReplaceAllVector','t':'ReplaceAllVector','c':1}])
+        add_pass('hlsl-dxil-legalize-resource-use', 'DxilLegalizeResourceUsePass', 'DXIL legalize resource use', [])
+        add_pass('hlsl-dxil-legalize-static-resource-use', 'DxilLegalizeStaticResourceUsePass', 'DXIL legalize static resource use', [])
         add_pass('dxilgen', 'DxilGenerationPass', 'HLSL DXIL Generation', [
             {'n':'NotOptimized','t':'bool','c':1}])
         add_pass('simplify-inst', 'SimplifyInst', 'Simplify Instructions', [])

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini