[llvm] [SPIR-V] Rework duplicate tracker and tracking of IR entities and types (PR #130605)

Vyacheslav Levytskyy via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 14 10:41:43 PDT 2025


https://github.com/VyacheslavLevytskyy updated https://github.com/llvm/llvm-project/pull/130605

>From 33221a17e7e0d4a12249a248ccbbff0a7df02ae4 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Mon, 10 Mar 2025 06:46:43 -0700
Subject: [PATCH 1/9] remove spv_track_constant() intrnal intrinsics

---
 llvm/include/llvm/IR/IntrinsicsSPIRV.td       |  2 +-
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp       |  9 +-
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 82 ++++++++++---------
 llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp   | 33 +++-----
 llvm/lib/Target/SPIRV/SPIRVUtils.cpp          | 19 ++---
 5 files changed, 65 insertions(+), 80 deletions(-)

diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 7012ef3534c68..89fb92be0e1eb 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -13,7 +13,7 @@
 let TargetPrefix = "spv" in {
   def int_spv_assign_type : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>;
   def int_spv_assign_ptr_type : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg<ArgIndex<2>>]>;
-  def int_spv_assign_name : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>;
+  def int_spv_assign_name : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>;
   def int_spv_assign_decoration : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>;
   def int_spv_value_md : Intrinsic<[], [llvm_metadata_ty]>;
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index 579e37f68d5d8..f5c31ea737839 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -391,12 +391,9 @@ static MachineInstr *getBlockStructInstr(Register ParamReg,
 // TODO: maybe unify with prelegalizer pass.
 static unsigned getConstFromIntrinsic(Register Reg, MachineRegisterInfo *MRI) {
   MachineInstr *DefMI = MRI->getUniqueVRegDef(Reg);
-  assert(isSpvIntrinsic(*DefMI, Intrinsic::spv_track_constant) &&
-         DefMI->getOperand(2).isReg());
-  MachineInstr *DefMI2 = MRI->getUniqueVRegDef(DefMI->getOperand(2).getReg());
-  assert(DefMI2->getOpcode() == TargetOpcode::G_CONSTANT &&
-         DefMI2->getOperand(1).isCImm());
-  return DefMI2->getOperand(1).getCImm()->getValue().getZExtValue();
+  assert(DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&
+         DefMI->getOperand(1).isCImm());
+  return DefMI->getOperand(1).getCImm()->getValue().getZExtValue();
 }
 
 // Return type of the instruction result from spv_assign_type intrinsic.
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 751ea5ab2dc47..356f4f6dab75c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -63,7 +63,7 @@ class SPIRVEmitIntrinsics
   SPIRVTargetMachine *TM = nullptr;
   SPIRVGlobalRegistry *GR = nullptr;
   Function *CurrF = nullptr;
-  bool TrackConstants = true;
+  bool TrackConstants = false;//true;
   bool HaveFunPtrs = false;
   DenseMap<Instruction *, Constant *> AggrConsts;
   DenseMap<Instruction *, Type *> AggrConstTypes;
@@ -316,8 +316,10 @@ static void emitAssignName(Instruction *I, IRBuilder<> &B) {
     return;
   reportFatalOnTokenType(I);
   setInsertPointAfterDef(B, I);
-  std::vector<Value *> Args = {I};
-  addStringImm(I->getName(), B, Args);
+  LLVMContext &Ctx = I->getContext();
+  std::vector<Value *> Args = {
+      I, MetadataAsValue::get(
+             Ctx, MDNode::get(Ctx, MDString::get(Ctx, I->getName())))};
   B.CreateIntrinsic(Intrinsic::spv_assign_name, {I->getType()}, Args);
 }
 
@@ -2023,7 +2025,7 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
   auto *II = dyn_cast<IntrinsicInst>(I);
   bool IsConstComposite =
       II && II->getIntrinsicID() == Intrinsic::spv_const_composite;
-  if (IsConstComposite && TrackConstants) {
+  if (IsConstComposite) {
     setInsertPointAfterDef(B, I);
     auto t = AggrConsts.find(I);
     assert(t != AggrConsts.end());
@@ -2035,41 +2037,43 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
   }
   bool IsPhi = isa<PHINode>(I), BPrepared = false;
   for (const auto &Op : I->operands()) {
-    if (isa<PHINode>(I) || isa<SwitchInst>(I))
-      TrackConstants = false;
-    if ((isa<ConstantData>(Op) || isa<ConstantExpr>(Op)) && TrackConstants) {
-      unsigned OpNo = Op.getOperandNo();
-      if (II && ((II->getIntrinsicID() == Intrinsic::spv_gep && OpNo == 0) ||
-                 (II->paramHasAttr(OpNo, Attribute::ImmArg))))
-        continue;
-      if (!BPrepared) {
-        IsPhi ? B.SetInsertPointPastAllocas(I->getParent()->getParent())
-              : B.SetInsertPoint(I);
-        BPrepared = true;
-      }
-      Type *OpTy = Op->getType();
-      Value *OpTyVal = Op;
-      if (OpTy->isTargetExtTy())
-        OpTyVal = getNormalizedPoisonValue(OpTy);
-      CallInst *NewOp =
-          buildIntrWithMD(Intrinsic::spv_track_constant,
-                          {OpTy, OpTyVal->getType()}, Op, OpTyVal, {}, B);
-      Type *OpElemTy = nullptr;
-      if (!IsConstComposite && isPointerTy(OpTy) &&
-          (OpElemTy = GR->findDeducedElementType(Op)) != nullptr &&
-          OpElemTy != IntegerType::getInt8Ty(I->getContext())) {
-        GR->buildAssignPtr(B, IntegerType::getInt8Ty(I->getContext()), NewOp);
-        SmallVector<Type *, 2> Types = {OpTy, OpTy};
-        SmallVector<Value *, 2> Args = {
-            NewOp, buildMD(getNormalizedPoisonValue(OpElemTy)),
-            B.getInt32(getPointerAddressSpace(OpTy))};
-        CallInst *PtrCasted =
-            B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
-        GR->buildAssignPtr(B, OpElemTy, PtrCasted);
-        NewOp = PtrCasted;
-      }
-      I->setOperand(OpNo, NewOp);
+    if (isa<PHINode>(I) || isa<SwitchInst>(I) ||
+        !(isa<ConstantData>(Op) || isa<ConstantExpr>(Op)))
+      continue;
+    unsigned OpNo = Op.getOperandNo();
+    if (II && ((II->getIntrinsicID() == Intrinsic::spv_gep && OpNo == 0) ||
+                (II->paramHasAttr(OpNo, Attribute::ImmArg))))
+      continue;
+
+    if (!BPrepared) {
+      IsPhi ? B.SetInsertPointPastAllocas(I->getParent()->getParent())
+            : B.SetInsertPoint(I);
+      BPrepared = true;
     }
+    Type *OpTy = Op->getType();
+    Value *OpTyVal = Op;
+    if (OpTy->isTargetExtTy())
+      OpTyVal = getNormalizedPoisonValue(OpTy);
+    Value *NewOp = Op;
+    if (OpTy->isTargetExtTy())
+      NewOp = buildIntrWithMD(Intrinsic::spv_track_constant,
+                              {OpTy, OpTyVal->getType()}, Op, OpTyVal, {}, B);
+    Type *OpElemTy = nullptr;
+    if (!IsConstComposite && isPointerTy(OpTy) &&
+        (OpElemTy = GR->findDeducedElementType(Op)) != nullptr &&
+        OpElemTy != IntegerType::getInt8Ty(I->getContext())) {
+      GR->buildAssignPtr(B, IntegerType::getInt8Ty(I->getContext()), NewOp);
+      SmallVector<Type *, 2> Types = {OpTy, OpTy};
+      SmallVector<Value *, 2> Args = {
+          NewOp, buildMD(getNormalizedPoisonValue(OpElemTy)),
+          B.getInt32(getPointerAddressSpace(OpTy))};
+      CallInst *PtrCasted =
+          B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
+      GR->buildAssignPtr(B, OpElemTy, PtrCasted);
+      NewOp = PtrCasted;
+    }
+    if (NewOp != Op)
+      I->setOperand(OpNo, NewOp);
   }
   emitAssignName(I, B);
 }
@@ -2417,7 +2421,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
         deduceOperandElementType(&Phi, nullptr);
 
   for (auto *I : Worklist) {
-    TrackConstants = true;
+    TrackConstants = false;//true;
     if (!I->getType()->isVoidTy() || isa<StoreInst>(I))
       setInsertPointAfterDef(B, I);
     // Visitors return either the original/newly created instruction for further
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index 3779a4b6ccd34..edf215f0ce00f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -133,32 +133,25 @@ addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR,
     MI->eraseFromParent();
 }
 
-static void
-foldConstantsIntoIntrinsics(MachineFunction &MF,
-                            const SmallSet<Register, 4> &TrackedConstRegs) {
-  SmallVector<MachineInstr *, 10> ToErase;
-  MachineRegisterInfo &MRI = MF.getRegInfo();
-  const unsigned AssignNameOperandShift = 2;
+static void foldConstantsIntoIntrinsics(MachineFunction &MF,
+                                        MachineIRBuilder MIB) {
+  SmallVector<MachineInstr *, 64> ToErase;
   for (MachineBasicBlock &MBB : MF) {
     for (MachineInstr &MI : MBB) {
       if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_name))
         continue;
-      unsigned NumOp = MI.getNumExplicitDefs() + AssignNameOperandShift;
-      while (MI.getOperand(NumOp).isReg()) {
-        MachineOperand &MOp = MI.getOperand(NumOp);
-        MachineInstr *ConstMI = MRI.getVRegDef(MOp.getReg());
-        assert(ConstMI->getOpcode() == TargetOpcode::G_CONSTANT);
-        MI.removeOperand(NumOp);
-        MI.addOperand(MachineOperand::CreateImm(
-            ConstMI->getOperand(1).getCImm()->getZExtValue()));
-        Register DefReg = ConstMI->getOperand(0).getReg();
-        if (MRI.use_empty(DefReg) && !TrackedConstRegs.contains(DefReg))
-          ToErase.push_back(ConstMI);
+      const MDNode *MD = MI.getOperand(2).getMetadata();
+      StringRef ValueName = cast<MDString>(MD->getOperand(0))->getString();
+      if (ValueName.size() > 0) {
+        MIB.setInsertPt(*MI.getParent(), MI);
+        buildOpName(MI.getOperand(1).getReg(), ValueName, MIB);
       }
+      ToErase.push_back(&MI);
     }
+    for (MachineInstr *MI : ToErase)
+      MI->eraseFromParent();
+    ToErase.clear();
   }
-  for (MachineInstr *MI : ToErase)
-    MI->eraseFromParent();
 }
 
 static MachineInstr *findAssignTypeInstr(Register Reg,
@@ -1043,7 +1036,7 @@ bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
   // to keep record of tracked constants
   SmallSet<Register, 4> TrackedConstRegs;
   addConstantsToTrack(MF, GR, ST, TargetExtConstTypes, TrackedConstRegs);
-  foldConstantsIntoIntrinsics(MF, TrackedConstRegs);
+  foldConstantsIntoIntrinsics(MF, MIB);
   insertBitcasts(MF, GR, MIB);
   generateAssignInstrs(MF, GR, MIB, TargetExtConstTypes);
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index ce4f6d6c9288f..05bebb5a0e9c1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -307,20 +307,11 @@ SPIRV::Scope::Scope getMemScope(LLVMContext &Ctx, SyncScope::ID Id) {
 MachineInstr *getDefInstrMaybeConstant(Register &ConstReg,
                                        const MachineRegisterInfo *MRI) {
   MachineInstr *MI = MRI->getVRegDef(ConstReg);
-  MachineInstr *ConstInstr =
-      MI->getOpcode() == SPIRV::G_TRUNC || MI->getOpcode() == SPIRV::G_ZEXT
-          ? MRI->getVRegDef(MI->getOperand(1).getReg())
-          : MI;
-  if (auto *GI = dyn_cast<GIntrinsic>(ConstInstr)) {
-    if (GI->is(Intrinsic::spv_track_constant)) {
-      ConstReg = ConstInstr->getOperand(2).getReg();
-      return MRI->getVRegDef(ConstReg);
-    }
-  } else if (ConstInstr->getOpcode() == SPIRV::ASSIGN_TYPE) {
-    ConstReg = ConstInstr->getOperand(1).getReg();
-    return MRI->getVRegDef(ConstReg);
-  }
-  return MRI->getVRegDef(ConstReg);
+  if (MI->getOpcode() == SPIRV::G_TRUNC || MI->getOpcode() == SPIRV::G_ZEXT)
+    return getDefInstrMaybeConstant(ConstReg = MI->getOperand(1).getReg(), MRI);
+  if (MI->getOpcode() == SPIRV::ASSIGN_TYPE)
+    return getDefInstrMaybeConstant(ConstReg = MI->getOperand(1).getReg(), MRI);
+  return MI;
 }
 
 uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI) {

>From c2fcf6357b015fc1272d3658ca45db604fb9b19b Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Mon, 10 Mar 2025 11:39:29 -0700
Subject: [PATCH 2/9] fixes

---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp       |  5 ++-
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 29 ++++++++---------
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h   |  3 +-
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 11 +++++++
 llvm/lib/Target/SPIRV/SPIRVUtils.cpp          | 32 +++++++++++++++++--
 .../test/CodeGen/SPIRV/SampledImageRetType.ll |  6 ++--
 6 files changed, 60 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index f5c31ea737839..e6c0a526a9cec 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -1968,8 +1968,7 @@ static bool generateReadImageInst(const StringRef DemangledCall,
       Sampler = GR->buildConstantSampler(
           Register(), getSamplerAddressingModeFromBitmask(SamplerMask),
           getSamplerParamFromBitmask(SamplerMask),
-          getSamplerFilterModeFromBitmask(SamplerMask), MIRBuilder,
-          GR->getSPIRVTypeForVReg(Sampler));
+          getSamplerFilterModeFromBitmask(SamplerMask), MIRBuilder);
     }
     SPIRVType *ImageType = GR->getSPIRVTypeForVReg(Image);
     SPIRVType *SampledImageType =
@@ -2056,7 +2055,7 @@ static bool generateSampleImageInst(const StringRef DemangledCall,
     Register Sampler = GR->buildConstantSampler(
         Call->ReturnRegister, getSamplerAddressingModeFromBitmask(Bitmask),
         getSamplerParamFromBitmask(Bitmask),
-        getSamplerFilterModeFromBitmask(Bitmask), MIRBuilder, Call->ReturnType);
+        getSamplerFilterModeFromBitmask(Bitmask), MIRBuilder);
     return Sampler.isValid();
   } else if (Call->Builtin->Name.contains_insensitive("__spirv_SampledImage")) {
     // Create OpSampledImage.
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index cbec1c95eadc3..fb718d9ddd0b4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -398,7 +398,9 @@ Register SPIRVGlobalRegistry::buildConstantInt(uint64_t Val,
                      SPIRV::AccessQualifier::ReadWrite, EmitIR);
     DT.add(ConstInt, &MIRBuilder.getMF(), Res);
     if (EmitIR) {
-      MIRBuilder.buildConstant(Res, *ConstInt);
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return MIRBuilder.buildConstant(Res, *ConstInt);
+      });
     } else {
       Register SpvTypeReg = getSPIRVTypeID(SpvType);
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
@@ -605,7 +607,9 @@ Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
     assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
     DT.add(CA, CurMF, SpvVecConst);
     if (EmitIR) {
-      MIRBuilder.buildSplatBuildVector(SpvVecConst, SpvScalConst);
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return MIRBuilder.buildSplatBuildVector(SpvVecConst, SpvScalConst);
+      });
     } else {
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
         if (Val) {
@@ -668,17 +672,10 @@ SPIRVGlobalRegistry::getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder,
   return Res;
 }
 
-Register SPIRVGlobalRegistry::buildConstantSampler(
-    Register ResReg, unsigned AddrMode, unsigned Param, unsigned FilerMode,
-    MachineIRBuilder &MIRBuilder, SPIRVType *SpvType) {
-  SPIRVType *SampTy;
-  if (SpvType)
-    SampTy = getOrCreateSPIRVType(getTypeForSPIRVType(SpvType), MIRBuilder,
-                                  SPIRV::AccessQualifier::ReadWrite, true);
-  else if ((SampTy = getOrCreateSPIRVTypeByName("opencl.sampler_t", MIRBuilder,
-                                                false)) == nullptr)
-    report_fatal_error("Unable to recognize SPIRV type name: opencl.sampler_t");
-
+Register
+SPIRVGlobalRegistry::buildConstantSampler(Register ResReg, unsigned AddrMode,
+                                          unsigned Param, unsigned FilerMode,
+                                          MachineIRBuilder &MIRBuilder) {
   auto Sampler =
       ResReg.isValid()
           ? ResReg
@@ -686,7 +683,7 @@ Register SPIRVGlobalRegistry::buildConstantSampler(
   auto Res = createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
     return MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
         .addDef(Sampler)
-        .addUse(getSPIRVTypeID(SampTy))
+        .addUse(getSPIRVTypeID(getOrCreateOpTypeSampler(MIRBuilder)))
         .addImm(AddrMode)
         .addImm(Param)
         .addImm(FilerMode);
@@ -1383,7 +1380,9 @@ SPIRVGlobalRegistry::getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder) {
     return Res;
   Register ResVReg = createTypeVReg(MIRBuilder);
   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
-  return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
+  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+    return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
+  });
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypePipe(
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index 89599f17ef737..467d9b73e2e39 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -544,8 +544,7 @@ class SPIRVGlobalRegistry {
                                    SPIRVType *SpvType);
   Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param,
                                 unsigned FilerMode,
-                                MachineIRBuilder &MIRBuilder,
-                                SPIRVType *SpvType);
+                                MachineIRBuilder &MIRBuilder);
   Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType,
                             const SPIRVInstrInfo &TII);
   Register buildGlobalVariable(Register Reg, SPIRVType *BaseType,
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index b188f36ca9a9e..ce9ce3ef3135c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -2326,6 +2326,17 @@ static bool isConstReg(MachineRegisterInfo *MRI, SPIRVType *OpDef,
         return false;
     }
     return true;
+  case SPIRV::OpConstantTrue:
+  case SPIRV::OpConstantFalse:
+  case SPIRV::OpConstantI:
+  case SPIRV::OpConstantF:
+  case SPIRV::OpConstantComposite:
+  case SPIRV::OpConstantCompositeContinuedINTEL:
+  case SPIRV::OpConstantSampler:
+  case SPIRV::OpConstantNull:
+  case SPIRV::OpUndef:
+  case SPIRV::OpConstantFunctionPointerINTEL:
+    return true;
   }
   }
   return false;
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index 05bebb5a0e9c1..8380cd579004d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -303,16 +303,42 @@ SPIRV::Scope::Scope getMemScope(LLVMContext &Ctx, SyncScope::ID Id) {
     return SPIRV::Scope::Device;
   return SPIRV::Scope::CrossDevice;
 }
-
+/*
 MachineInstr *getDefInstrMaybeConstant(Register &ConstReg,
                                        const MachineRegisterInfo *MRI) {
   MachineInstr *MI = MRI->getVRegDef(ConstReg);
-  if (MI->getOpcode() == SPIRV::G_TRUNC || MI->getOpcode() == SPIRV::G_ZEXT)
-    return getDefInstrMaybeConstant(ConstReg = MI->getOperand(1).getReg(), MRI);
+  //if (MI->getOpcode() == SPIRV::G_TRUNC || MI->getOpcode() == SPIRV::G_ZEXT)
+  //  return getDefInstrMaybeConstant(ConstReg = MI->getOperand(1).getReg(), MRI);
   if (MI->getOpcode() == SPIRV::ASSIGN_TYPE)
     return getDefInstrMaybeConstant(ConstReg = MI->getOperand(1).getReg(), MRI);
+  if (auto *GI = dyn_cast<GIntrinsic>(MI))
+    if (GI->is(Intrinsic::spv_track_constant))
+      return MRI->getVRegDef(ConstReg = MI->getOperand(2).getReg());
   return MI;
 }
+*/
+MachineInstr *getDefInstrMaybeConstant(Register &ConstReg,
+                                       const MachineRegisterInfo *MRI) {
+  MachineInstr *MI = MRI->getVRegDef(ConstReg);
+  MachineInstr *ConstInstr =
+      MI->getOpcode() == SPIRV::G_TRUNC || MI->getOpcode() == SPIRV::G_ZEXT
+          ? MRI->getVRegDef(MI->getOperand(1).getReg())
+          : MI;
+  if (auto *GI = dyn_cast<GIntrinsic>(ConstInstr)) {
+    if (GI->is(Intrinsic::spv_track_constant)) {
+      ConstReg = ConstInstr->getOperand(2).getReg();
+      return MRI->getVRegDef(ConstReg);
+    }
+  } else if (ConstInstr->getOpcode() == SPIRV::ASSIGN_TYPE) {
+    ConstReg = ConstInstr->getOperand(1).getReg();
+    return MRI->getVRegDef(ConstReg);
+  } else if (ConstInstr->getOpcode() == TargetOpcode::G_CONSTANT ||
+             ConstInstr->getOpcode() == TargetOpcode::G_FCONSTANT) {
+    ConstReg = ConstInstr->getOperand(0).getReg();
+    return ConstInstr;
+  }
+  return MRI->getVRegDef(ConstReg);
+}
 
 uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI) {
   const MachineInstr *MI = getDefInstrMaybeConstant(ConstReg, MRI);
diff --git a/llvm/test/CodeGen/SPIRV/SampledImageRetType.ll b/llvm/test/CodeGen/SPIRV/SampledImageRetType.ll
index f034f293dc6a9..91f83e09c94f0 100644
--- a/llvm/test/CodeGen/SPIRV/SampledImageRetType.ll
+++ b/llvm/test/CodeGen/SPIRV/SampledImageRetType.ll
@@ -4,9 +4,9 @@
 ; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
-; CHECK: %[[#image1d_t:]] = OpTypeImage
-; CHECK: %[[#sampler_t:]] = OpTypeSampler
-; CHECK: %[[#sampled_image_t:]] = OpTypeSampledImage
+; CHECK-DAG: %[[#image1d_t:]] = OpTypeImage
+; CHECK-DAG: %[[#sampler_t:]] = OpTypeSampler
+; CHECK-DAG: %[[#sampled_image_t:]] = OpTypeSampledImage
 
 declare dso_local spir_func ptr addrspace(4) @_Z20__spirv_SampledImageI14ocl_image1d_roPvET0_T_11ocl_sampler(target("spirv.Image", void, 0, 0, 0, 0, 0, 0, 0) %0, target("spirv.Sampler") %1) local_unnamed_addr
 

>From 663108c10f9fbd46075d1710dd0beb21a1918331 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Tue, 11 Mar 2025 04:44:05 -0700
Subject: [PATCH 3/9] remove duplicate tracker

---
 .../lib/Target/SPIRV/SPIRVDuplicatesTracker.h | 228 ++++-----------
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 275 +++++++-----------
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h   |  41 +--
 3 files changed, 165 insertions(+), 379 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
index 441e32c1eb695..21e1069adb2d3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
+++ b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
@@ -26,35 +26,8 @@
 
 namespace llvm {
 namespace SPIRV {
-class SPIRVInstrInfo;
-// NOTE: using MapVector instead of DenseMap because it helps getting
-// everything ordered in a stable manner for a price of extra (NumKeys)*PtrSize
-// memory and expensive removals which do not happen anyway.
-class DTSortableEntry : public MapVector<const MachineFunction *, Register> {
-  SmallVector<DTSortableEntry *, 2> Deps;
 
-  struct FlagsTy {
-    unsigned IsFunc : 1;
-    unsigned IsGV : 1;
-    unsigned IsConst : 1;
-    // NOTE: bit-field default init is a C++20 feature.
-    FlagsTy() : IsFunc(0), IsGV(0), IsConst(0) {}
-  };
-  FlagsTy Flags;
-
-public:
-  // Common hoisting utility doesn't support function, because their hoisting
-  // require hoisting of params as well.
-  bool getIsFunc() const { return Flags.IsFunc; }
-  bool getIsGV() const { return Flags.IsGV; }
-  bool getIsConst() const { return Flags.IsConst; }
-  void setIsFunc(bool V) { Flags.IsFunc = V; }
-  void setIsGV(bool V) { Flags.IsGV = V; }
-  void setIsConst(bool V) { Flags.IsConst = V; }
-
-  const SmallVector<DTSortableEntry *, 2> &getDeps() const { return Deps; }
-  void addDep(DTSortableEntry *E) { Deps.push_back(E); }
-};
+using IRHandle = std::tuple<const void *, unsigned, unsigned>;
 
 enum SpecialTypeKind {
   STK_Empty = 0,
@@ -63,12 +36,11 @@ enum SpecialTypeKind {
   STK_Sampler,
   STK_Pipe,
   STK_DeviceEvent,
+  STK_ElementPointer,
   STK_Pointer,
   STK_Last = -1
 };
 
-using SpecialTypeDescriptor = std::tuple<const Type *, unsigned, unsigned>;
-
 union ImageAttrs {
   struct BitFlags {
     unsigned Dim : 3;
@@ -94,18 +66,18 @@ union ImageAttrs {
   }
 };
 
-inline SpecialTypeDescriptor
-make_descr_image(const Type *SampledTy, unsigned Dim, unsigned Depth,
-                 unsigned Arrayed, unsigned MS, unsigned Sampled,
-                 unsigned ImageFormat, unsigned AQ = 0) {
+inline IRHandle make_descr_image(const Type *SampledTy, unsigned Dim,
+                                 unsigned Depth, unsigned Arrayed, unsigned MS,
+                                 unsigned Sampled, unsigned ImageFormat,
+                                 unsigned AQ = 0) {
   return std::make_tuple(
       SampledTy,
       ImageAttrs(Dim, Depth, Arrayed, MS, Sampled, ImageFormat, AQ).Val,
       SpecialTypeKind::STK_Image);
 }
 
-inline SpecialTypeDescriptor
-make_descr_sampled_image(const Type *SampledTy, const MachineInstr *ImageTy) {
+inline IRHandle make_descr_sampled_image(const Type *SampledTy,
+                                         const MachineInstr *ImageTy) {
   assert(ImageTy->getOpcode() == SPIRV::OpTypeImage);
   unsigned AC = AccessQualifier::AccessQualifier::None;
   if (ImageTy->getNumOperands() > 8)
@@ -120,170 +92,84 @@ make_descr_sampled_image(const Type *SampledTy, const MachineInstr *ImageTy) {
       SpecialTypeKind::STK_SampledImage);
 }
 
-inline SpecialTypeDescriptor make_descr_sampler() {
+inline IRHandle make_descr_sampler() {
   return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_Sampler);
 }
 
-inline SpecialTypeDescriptor make_descr_pipe(uint8_t AQ) {
+inline IRHandle make_descr_pipe(uint8_t AQ) {
   return std::make_tuple(nullptr, AQ, SpecialTypeKind::STK_Pipe);
 }
 
-inline SpecialTypeDescriptor make_descr_event() {
+inline IRHandle make_descr_event() {
   return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_DeviceEvent);
 }
 
-inline SpecialTypeDescriptor make_descr_pointee(const Type *ElementType,
-                                                unsigned AddressSpace) {
+inline IRHandle make_descr_pointee(const Type *ElementType,
+                                   unsigned AddressSpace) {
   return std::make_tuple(ElementType, AddressSpace,
-                         SpecialTypeKind::STK_Pointer);
+                         SpecialTypeKind::STK_ElementPointer);
 }
-} // namespace SPIRV
 
-template <typename KeyTy> class SPIRVDuplicatesTrackerBase {
-public:
-  // NOTE: using MapVector instead of DenseMap helps getting everything ordered
-  // in a stable manner for a price of extra (NumKeys)*PtrSize memory and
-  // expensive removals which don't happen anyway.
-  using StorageTy = MapVector<KeyTy, SPIRV::DTSortableEntry>;
+inline IRHandle make_descr_ptr(const void *Ptr) {
+  return std::make_tuple(Ptr, 0U, SpecialTypeKind::STK_Pointer);
+}
+} // namespace SPIRV
 
-private:
-  StorageTy Storage;
+// Bi-directional mappings between LLVM entities and (v-reg, machine function)
+// pairs support management of unique SPIR-V definitions per machine function
+// per an LLVM/GlobalISel entity (e.g., Type, Constant, Machine Instruction).
+class SPIRVIRMap {
+  DenseMap < std::pair<IRHandle, const MachineFunction *>, Register >> Vregs;
+  DenseMap<const MachineInstr *, IRHandle> Defs;
 
 public:
-  void add(KeyTy V, const MachineFunction *MF, Register R) {
-    if (find(V, MF).isValid())
-      return;
-
-    auto &S = Storage[V];
-    S[MF] = R;
-    if (std::is_same<Function,
-                     typename std::remove_const<
-                         typename std::remove_pointer<KeyTy>::type>::type>() ||
-        std::is_same<Argument,
-                     typename std::remove_const<
-                         typename std::remove_pointer<KeyTy>::type>::type>())
-      S.setIsFunc(true);
-    if (std::is_same<GlobalVariable,
-                     typename std::remove_const<
-                         typename std::remove_pointer<KeyTy>::type>::type>())
-      S.setIsGV(true);
-    if (std::is_same<Constant,
-                     typename std::remove_const<
-                         typename std::remove_pointer<KeyTy>::type>::type>())
-      S.setIsConst(true);
-  }
-
-  Register find(KeyTy V, const MachineFunction *MF) const {
-    auto iter = Storage.find(V);
-    if (iter != Storage.end()) {
-      auto Map = iter->second;
-      auto iter2 = Map.find(MF);
-      if (iter2 != Map.end())
-        return iter2->second;
+  bool add(IRHandle Handle, const MachineInstr *MI) {
+    auto [It, Inserted] =
+        Vregs.try_emplace(std::make_pair(Handle, MI->getMF()));
+    if (Inserted) {
+      It->second = MI->getOperand(0).getReg();
+      auto [_, IsConsistent] = Defs.insert_or_assign(MI, Handle);
+      assert(IsConsistent);
     }
-    return Register();
-  }
-
-  const StorageTy &getAllUses() const { return Storage; }
-
-private:
-  StorageTy &getAllUses() { return Storage; }
-
-  // The friend class needs to have access to the internal storage
-  // to be able to build dependency graph, can't declare only one
-  // function a 'friend' due to the incomplete declaration at this point
-  // and mutual dependency problems.
-  friend class SPIRVGeneralDuplicatesTracker;
-};
-
-template <typename T>
-class SPIRVDuplicatesTracker : public SPIRVDuplicatesTrackerBase<const T *> {};
-
-template <>
-class SPIRVDuplicatesTracker<SPIRV::SpecialTypeDescriptor>
-    : public SPIRVDuplicatesTrackerBase<SPIRV::SpecialTypeDescriptor> {};
-
-class SPIRVGeneralDuplicatesTracker {
-  SPIRVDuplicatesTracker<Type> TT;
-  SPIRVDuplicatesTracker<Constant> CT;
-  SPIRVDuplicatesTracker<GlobalVariable> GT;
-  SPIRVDuplicatesTracker<Function> FT;
-  SPIRVDuplicatesTracker<Argument> AT;
-  SPIRVDuplicatesTracker<MachineInstr> MT;
-  SPIRVDuplicatesTracker<SPIRV::SpecialTypeDescriptor> ST;
-
-public:
-  void add(const Type *Ty, const MachineFunction *MF, Register R) {
-    TT.add(unifyPtrType(Ty), MF, R);
-  }
-
-  void add(const Type *PointeeTy, unsigned AddressSpace,
-           const MachineFunction *MF, Register R) {
-    ST.add(SPIRV::make_descr_pointee(unifyPtrType(PointeeTy), AddressSpace), MF,
-           R);
+    return Inserted1;
   }
-
-  void add(const Constant *C, const MachineFunction *MF, Register R) {
-    CT.add(C, MF, R);
+  bool erase(const MachineInstr *MI) {
+    bool Res = false;
+    if (auto It = Defs.find(MI); It != Defs.end()) {
+      Res = Vregs.erase(std::make_pair(It->second, MI->getMF()));
+      Defs.erase(It);
+    }
+    return Res;
   }
-
-  void add(const GlobalVariable *GV, const MachineFunction *MF, Register R) {
-    GT.add(GV, MF, R);
+  Register find(IRHandle Handle, const MachineFunction *MF) {
+    if (auto It = Vregs.find(std::make_pair(Handle, MF)); It != Vregs.end())
+      return It->second;
+    return Register();
   }
 
-  void add(const Function *F, const MachineFunction *MF, Register R) {
-    FT.add(F, MF, R);
+  // helpers
+  bool add(const Type *Ty, const MachineInstr *MI) {
+    return add(SPIRV::make_descr_ptr(unifyPtrType(Ty)), MI);
   }
-
-  void add(const Argument *Arg, const MachineFunction *MF, Register R) {
-    AT.add(Arg, MF, R);
+  void add(const void *Key, const MachineInstr *MI) {
+    return add(SPIRV::make_descr_ptr(Key), MI);
   }
-
-  void add(const MachineInstr *MI, const MachineFunction *MF, Register R) {
-    MT.add(MI, MF, R);
+  bool add(const Type *PointeeTy, unsigned AddressSpace,
+           const MachineInstr *MI) {
+    return add(SPIRV::make_descr_pointee(unifyPtrType(PointeeTy), AddressSpace),
+               MI);
   }
-
-  void add(const SPIRV::SpecialTypeDescriptor &TD, const MachineFunction *MF,
-           Register R) {
-    ST.add(TD, MF, R);
-  }
-
   Register find(const Type *Ty, const MachineFunction *MF) {
-    return TT.find(unifyPtrType(Ty), MF);
+    return find(SPIRV::make_descr_ptr(unifyPtrType(Ty)), MF);
+  }
+  Register find(const void *Key, const MachineFunction *MF) {
+    return find(SPIRV::make_descr_ptr(Key), MF);
   }
-
   Register find(const Type *PointeeTy, unsigned AddressSpace,
                 const MachineFunction *MF) {
-    return ST.find(
+    return find(
         SPIRV::make_descr_pointee(unifyPtrType(PointeeTy), AddressSpace), MF);
   }
-
-  Register find(const Constant *C, const MachineFunction *MF) {
-    return CT.find(const_cast<Constant *>(C), MF);
-  }
-
-  Register find(const GlobalVariable *GV, const MachineFunction *MF) {
-    return GT.find(const_cast<GlobalVariable *>(GV), MF);
-  }
-
-  Register find(const Function *F, const MachineFunction *MF) {
-    return FT.find(const_cast<Function *>(F), MF);
-  }
-
-  Register find(const Argument *Arg, const MachineFunction *MF) {
-    return AT.find(const_cast<Argument *>(Arg), MF);
-  }
-
-  Register find(const MachineInstr *MI, const MachineFunction *MF) {
-    return MT.find(const_cast<MachineInstr *>(MI), MF);
-  }
-
-  Register find(const SPIRV::SpecialTypeDescriptor &TD,
-                const MachineFunction *MF) {
-    return ST.find(TD, MF);
-  }
-
-  const SPIRVDuplicatesTracker<Type> *getTypes() { return &TT; }
 };
 } // namespace llvm
 #endif // LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index fb718d9ddd0b4..c897026dc2426 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -181,7 +181,7 @@ void SPIRVGlobalRegistry::invalidateMachineInstr(MachineInstr *MI) {
   // - take into account duplicate tracker case which is a known issue,
   // - review other data structure wrt. possible issues related to removal
   //   of a machine instruction during instruction selection.
-  const MachineFunction *MF = MI->getParent()->getParent();
+  const MachineFunction *MF = MI->getMF();
   auto It = LastInsertedTypeMap.find(MF);
   if (It == LastInsertedTypeMap.end())
     return;
@@ -245,98 +245,46 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
   });
 }
 
-std::tuple<Register, ConstantInt *, bool, unsigned>
-SPIRVGlobalRegistry::getOrCreateConstIntReg(uint64_t Val, SPIRVType *SpvType,
-                                            MachineIRBuilder *MIRBuilder,
-                                            MachineInstr *I,
-                                            const SPIRVInstrInfo *TII) {
-  assert(SpvType);
-  const IntegerType *LLVMIntTy =
-      cast<IntegerType>(getTypeForSPIRVType(SpvType));
-  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
-  bool NewInstr = false;
-  // Find a constant in DT or build a new one.
-  ConstantInt *CI = ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
-  Register Res = DT.find(CI, CurMF);
-  if (!Res.isValid()) {
-    Res =
-        CurMF->getRegInfo().createGenericVirtualRegister(LLT::scalar(BitWidth));
-    CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
-    if (MIRBuilder)
-      assignTypeToVReg(LLVMIntTy, Res, *MIRBuilder,
-                       SPIRV::AccessQualifier::ReadWrite, true);
-    else
-      assignIntTypeToVReg(BitWidth, Res, *I, *TII);
-    DT.add(CI, CurMF, Res);
-    NewInstr = true;
-  }
-  return std::make_tuple(Res, CI, NewInstr, BitWidth);
-}
-
-std::tuple<Register, ConstantFP *, bool, unsigned>
-SPIRVGlobalRegistry::getOrCreateConstFloatReg(APFloat Val, SPIRVType *SpvType,
-                                              MachineIRBuilder *MIRBuilder,
-                                              MachineInstr *I,
-                                              const SPIRVInstrInfo *TII) {
-  assert(SpvType);
-  LLVMContext &Ctx = CurMF->getFunction().getContext();
-  const Type *LLVMFloatTy = getTypeForSPIRVType(SpvType);
-  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
-  bool NewInstr = false;
-  // Find a constant in DT or build a new one.
-  auto *const CI = ConstantFP::get(Ctx, Val);
-  Register Res = DT.find(CI, CurMF);
-  if (!Res.isValid()) {
-    Res =
-        CurMF->getRegInfo().createGenericVirtualRegister(LLT::scalar(BitWidth));
-    CurMF->getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
-    if (MIRBuilder)
-      assignTypeToVReg(LLVMFloatTy, Res, *MIRBuilder,
-                       SPIRV::AccessQualifier::ReadWrite, true);
-    else
-      assignFloatTypeToVReg(BitWidth, Res, *I, *TII);
-    DT.add(CI, CurMF, Res);
-    NewInstr = true;
-  }
-  return std::make_tuple(Res, CI, NewInstr, BitWidth);
-}
-
 Register SPIRVGlobalRegistry::getOrCreateConstFP(APFloat Val, MachineInstr &I,
                                                  SPIRVType *SpvType,
                                                  const SPIRVInstrInfo &TII,
                                                  bool ZeroAsNull) {
-  assert(SpvType);
-  ConstantFP *CI;
-  Register Res;
-  bool New;
-  unsigned BitWidth;
-  std::tie(Res, CI, New, BitWidth) =
-      getOrCreateConstFloatReg(Val, SpvType, nullptr, &I, &TII);
-  // If we have found Res register which is defined by the passed G_CONSTANT
-  // machine instruction, a new constant instruction should be created.
-  if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
+  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
+  LLVMContext &Ctx = CurMF->getFunction().getContext();
+  auto *const CF = ConstantFP::get(Ctx, Val);
+  Register Res = find(CF, CurMF);
+  if (Res.isValid())
     return Res;
+
+  LLT LLTy = LLT::scalar(BitWidth);
+  Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
+  CurMF->getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
+  assignFloatTypeToVReg(BitWidth, Res, I, TII);
+
   MachineIRBuilder MIRBuilder(I);
-  createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-    MachineInstrBuilder MIB;
-    // In OpenCL OpConstantNull - Scalar floating point: +0.0 (all bits 0)
-    if (Val.isPosZero() && ZeroAsNull) {
-      MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
-                .addDef(Res)
-                .addUse(getSPIRVTypeID(SpvType));
-    } else {
-      MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
-                .addDef(Res)
-                .addUse(getSPIRVTypeID(SpvType));
-      addNumImm(
-          APInt(BitWidth, CI->getValueAPF().bitcastToAPInt().getZExtValue()),
-          MIB);
-    }
-    const auto &ST = CurMF->getSubtarget();
-    constrainSelectedInstRegOperands(
-        *MIB, *ST.getInstrInfo(), *ST.getRegisterInfo(), *ST.getRegBankInfo());
-    return MIB;
-  });
+  SPIRVType *NewType =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        MachineInstrBuilder MIB;
+        // In OpenCL OpConstantNull - Scalar floating point: +0.0 (all bits 0)
+        if (Val.isPosZero() && ZeroAsNull) {
+          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
+                    .addDef(Res)
+                    .addUse(getSPIRVTypeID(SpvType));
+        } else {
+          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
+                    .addDef(Res)
+                    .addUse(getSPIRVTypeID(SpvType));
+          addNumImm(APInt(BitWidth,
+                          CI->getValueAPF().bitcastToAPInt().getZExtValue()),
+                    MIB);
+        }
+        const auto &ST = CurMF->getSubtarget();
+        constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
+                                         *ST.getRegisterInfo(),
+                                         *ST.getRegBankInfo());
+        return MIB;
+      });
+  add(CI, NewType);
   return Res;
 }
 
@@ -344,36 +292,37 @@ Register SPIRVGlobalRegistry::getOrCreateConstInt(uint64_t Val, MachineInstr &I,
                                                   SPIRVType *SpvType,
                                                   const SPIRVInstrInfo &TII,
                                                   bool ZeroAsNull) {
-  assert(SpvType);
-  ConstantInt *CI;
-  Register Res;
-  bool New;
-  unsigned BitWidth;
-  std::tie(Res, CI, New, BitWidth) =
-      getOrCreateConstIntReg(Val, SpvType, nullptr, &I, &TII);
-  // If we have found Res register which is defined by the passed G_CONSTANT
-  // machine instruction, a new constant instruction should be created.
-  if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
+  const IntegerType *Ty = cast<IntegerType>(getTypeForSPIRVType(SpvType));
+  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
+  auto *const CI = ConstantInt::get(const_cast<IntegerType *>(Ty), Val);
+  Register Res = find(CI, CurMF);
+  if (Res.isValid())
     return Res;
-
+  LLT LLTy = LLT::scalar(BitWidth);
+  Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
+  CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
+  assignIntTypeToVReg(BitWidth, Res, I, TII);
   MachineIRBuilder MIRBuilder(I);
-  createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-    MachineInstrBuilder MIB;
-    if (Val || !ZeroAsNull) {
-      MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
-                .addDef(Res)
-                .addUse(getSPIRVTypeID(SpvType));
-      addNumImm(APInt(BitWidth, Val), MIB);
-    } else {
-      MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
-                .addDef(Res)
-                .addUse(getSPIRVTypeID(SpvType));
-    }
-    const auto &ST = CurMF->getSubtarget();
-    constrainSelectedInstRegOperands(
-        *MIB, *ST.getInstrInfo(), *ST.getRegisterInfo(), *ST.getRegBankInfo());
-    return MIB;
-  });
+  SPIRVType *NewType =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        MachineInstrBuilder MIB;
+        if (Val || !ZeroAsNull) {
+          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
+                    .addDef(Res)
+                    .addUse(getSPIRVTypeID(SpvType));
+          addNumImm(APInt(BitWidth, Val), MIB);
+        } else {
+          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
+                    .addDef(Res)
+                    .addUse(getSPIRVTypeID(SpvType));
+        }
+        const auto &ST = CurMF->getSubtarget();
+        constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
+                                         *ST.getRegisterInfo(),
+                                         *ST.getRegBankInfo());
+        return MIB;
+      });
+  add(CI, NewType);
   return Res;
 }
 
@@ -383,27 +332,24 @@ Register SPIRVGlobalRegistry::buildConstantInt(uint64_t Val,
                                                bool ZeroAsNull) {
   assert(SpvType);
   auto &MF = MIRBuilder.getMF();
-  const IntegerType *LLVMIntTy =
-      cast<IntegerType>(getTypeForSPIRVType(SpvType));
-  // Find a constant in DT or build a new one.
-  const auto ConstInt =
-      ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
-  Register Res = DT.find(ConstInt, &MF);
-  if (!Res.isValid()) {
-    unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
-    LLT LLTy = LLT::scalar(BitWidth);
-    Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
-    MF.getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
-    assignTypeToVReg(LLVMIntTy, Res, MIRBuilder,
-                     SPIRV::AccessQualifier::ReadWrite, EmitIR);
-    DT.add(ConstInt, &MIRBuilder.getMF(), Res);
-    if (EmitIR) {
-      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-        return MIRBuilder.buildConstant(Res, *ConstInt);
-      });
-    } else {
-      Register SpvTypeReg = getSPIRVTypeID(SpvType);
+  const IntegerType *Ty = cast<IntegerType>(getTypeForSPIRVType(SpvType));
+  auto *const CI = ConstantInt::get(const_cast<IntegerType *>(Ty), Val);
+  Register Res = find(CI, &MF);
+  if (Res.isValid())
+    return Res;
+
+  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
+  LLT LLTy = LLT::scalar(BitWidth);
+  Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
+  MF.getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
+  assignTypeToVReg(Ty, Res, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
+                   EmitIR);
+
+  SPIRVType *NewType =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        if (EmitIR)
+          return MIRBuilder.buildConstant(Res, *CI);
+        Register SpvTypeReg = getSPIRVTypeID(SpvType);
         MachineInstrBuilder MIB;
         if (Val || !ZeroAsNull) {
           MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
@@ -421,8 +367,7 @@ Register SPIRVGlobalRegistry::buildConstantInt(uint64_t Val,
                                          *Subtarget.getRegBankInfo());
         return MIB;
       });
-    }
-  }
+  add(ConstInt, NewType);
   return Res;
 }
 
@@ -430,31 +375,30 @@ Register SPIRVGlobalRegistry::buildConstantFP(APFloat Val,
                                               MachineIRBuilder &MIRBuilder,
                                               SPIRVType *SpvType) {
   auto &MF = MIRBuilder.getMF();
-  auto &Ctx = MF.getFunction().getContext();
-  if (!SpvType) {
-    const Type *LLVMFPTy = Type::getFloatTy(Ctx);
-    SpvType = getOrCreateSPIRVType(LLVMFPTy, MIRBuilder,
-                                   SPIRV::AccessQualifier::ReadWrite, true);
-  }
-  // Find a constant in DT or build a new one.
-  const auto ConstFP = ConstantFP::get(Ctx, Val);
-  Register Res = DT.find(ConstFP, &MF);
-  if (!Res.isValid()) {
-    Res = MF.getRegInfo().createGenericVirtualRegister(
-        LLT::scalar(getScalarOrVectorBitWidth(SpvType)));
-    MF.getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
-    assignSPIRVTypeToVReg(SpvType, Res, MF);
-    DT.add(ConstFP, &MF, Res);
-    createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-      MachineInstrBuilder MIB;
-      MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
-                .addDef(Res)
-                .addUse(getSPIRVTypeID(SpvType));
-      addNumImm(ConstFP->getValueAPF().bitcastToAPInt(), MIB);
-      return MIB;
-    });
-  }
+  if (!SpvType)
+    SpvType = getOrCreateSPIRVType(
+        Type::getFloatTy(MF.getFunction().getContext()), MIRBuilder,
+        SPIRV::AccessQualifier::ReadWrite, true);
+  auto *const CF = ConstantFP::get(Ctx, Val);
+  Register Res = find(CF, &MF);
+  if (Res.isValid())
+    return Res;
 
+  LLT LLTy = LLT::scalar(getScalarOrVectorBitWidth(SpvType));
+  Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
+  MF.getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
+  assignSPIRVTypeToVReg(SpvType, Res, MF);
+
+  SPIRVType *NewType =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        MachineInstrBuilder MIB;
+        MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
+                  .addDef(Res)
+                  .addUse(getSPIRVTypeID(SpvType));
+        addNumImm(CF->getValueAPF().bitcastToAPInt(), MIB);
+        return MIB;
+      });
+  add(CF, NewType);
   return Res;
 }
 
@@ -1044,13 +988,8 @@ SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
     SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
   if (isSpecialOpaqueType(Ty))
     return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
-  auto &TypeToSPIRVTypeMap = DT.getTypes()->getAllUses();
-  auto t = TypeToSPIRVTypeMap.find(Ty);
-  if (t != TypeToSPIRVTypeMap.end()) {
-    auto tt = t->second.find(&MIRBuilder.getMF());
-    if (tt != t->second.end())
-      return getSPIRVTypeForVReg(tt->second);
-  }
+  if (Register TyReg = DT.find(Ty, &MIRBuilder.getMF()); TyReg.isValid())
+    return getSPIRVTypeForVReg(TyReg);
 
   if (auto IType = dyn_cast<IntegerType>(Ty)) {
     const unsigned Width = IType->getBitWidth();
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index 467d9b73e2e39..8840401fe996d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -27,7 +27,7 @@ namespace llvm {
 class SPIRVSubtarget;
 using SPIRVType = const MachineInstr;
 
-class SPIRVGlobalRegistry {
+class SPIRVGlobalRegistry : public SPIRVIRMap {
   // Registers holding values which have types associated with them.
   // Initialized upon VReg definition in IRTranslator.
   // Do not confuse this with DuplicatesTracker as DT maps Type* to <MF, Reg>
@@ -37,9 +37,6 @@ class SPIRVGlobalRegistry {
   DenseMap<const MachineFunction *, DenseMap<Register, SPIRVType *>>
       VRegToTypeMap;
 
-  // Map LLVM Type* to <MF, Reg>
-  SPIRVGeneralDuplicatesTracker DT;
-
   DenseMap<SPIRVType *, const Type *> SPIRVToLLVMType;
 
   // map a Function to its definition (as a machine instruction operand)
@@ -119,42 +116,6 @@ class SPIRVGlobalRegistry {
 
   MachineFunction *CurMF;
 
-  void add(const Constant *C, MachineFunction *MF, Register R) {
-    DT.add(C, MF, R);
-  }
-
-  void add(const GlobalVariable *GV, MachineFunction *MF, Register R) {
-    DT.add(GV, MF, R);
-  }
-
-  void add(const Function *F, MachineFunction *MF, Register R) {
-    DT.add(F, MF, R);
-  }
-
-  void add(const Argument *Arg, MachineFunction *MF, Register R) {
-    DT.add(Arg, MF, R);
-  }
-
-  void add(const MachineInstr *MI, MachineFunction *MF, Register R) {
-    DT.add(MI, MF, R);
-  }
-
-  Register find(const MachineInstr *MI, MachineFunction *MF) {
-    return DT.find(MI, MF);
-  }
-
-  Register find(const Constant *C, MachineFunction *MF) {
-    return DT.find(C, MF);
-  }
-
-  Register find(const GlobalVariable *GV, MachineFunction *MF) {
-    return DT.find(GV, MF);
-  }
-
-  Register find(const Function *F, MachineFunction *MF) {
-    return DT.find(F, MF);
-  }
-
   void setBound(unsigned V) { Bound = V; }
   unsigned getBound() { return Bound; }
 

>From 5da3d35fe0a1e8292f11f5746ad7c24697f0199e Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Tue, 11 Mar 2025 05:37:03 -0700
Subject: [PATCH 4/9] add a new duplicate tracker

---
 .../lib/Target/SPIRV/SPIRVDuplicatesTracker.h |  14 +-
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 361 +++++++++---------
 2 files changed, 192 insertions(+), 183 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
index 21e1069adb2d3..aa3171f3e7d10 100644
--- a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
+++ b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
@@ -119,15 +119,15 @@ inline IRHandle make_descr_ptr(const void *Ptr) {
 // pairs support management of unique SPIR-V definitions per machine function
 // per an LLVM/GlobalISel entity (e.g., Type, Constant, Machine Instruction).
 class SPIRVIRMap {
-  DenseMap < std::pair<IRHandle, const MachineFunction *>, Register >> Vregs;
+  DenseMap < std::pair<IRHandle, const MachineFunction *>,
+      const MachineInstr *MI >> Vregs;
   DenseMap<const MachineInstr *, IRHandle> Defs;
 
 public:
   bool add(IRHandle Handle, const MachineInstr *MI) {
     auto [It, Inserted] =
-        Vregs.try_emplace(std::make_pair(Handle, MI->getMF()));
+        Vregs.try_emplace(std::make_pair(Handle, MI->getMF()), MI);
     if (Inserted) {
-      It->second = MI->getOperand(0).getReg();
       auto [_, IsConsistent] = Defs.insert_or_assign(MI, Handle);
       assert(IsConsistent);
     }
@@ -141,10 +141,14 @@ class SPIRVIRMap {
     }
     return Res;
   }
-  Register find(IRHandle Handle, const MachineFunction *MF) {
+  const MachineInstr *findMI(IRHandle Handle, const MachineFunction *MF) {
     if (auto It = Vregs.find(std::make_pair(Handle, MF)); It != Vregs.end())
       return It->second;
-    return Register();
+    return nullptr;
+  }
+  Register find(IRHandle Handle, const MachineFunction *MF) {
+    const MachineInstr *MI = findMI(Handle, MF);
+    return MI ? MI->getOperand(0).getReg() : Register();
   }
 
   // helpers
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index c897026dc2426..c0735f380f82b 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -426,47 +426,42 @@ Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull(
     Constant *Val, MachineInstr &I, SPIRVType *SpvType,
     const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
     unsigned ElemCnt, bool ZeroAsNull) {
-  // Find a constant vector or array in DT or build a new one.
-  Register Res = DT.find(CA, CurMF);
-  // If no values are attached, the composite is null constant.
+  if (Register R = find(CA, CurMF); R.isValid())
+    return R;
+
   bool IsNull = Val->isNullValue() && ZeroAsNull;
-  if (!Res.isValid()) {
-    // SpvScalConst should be created before SpvVecConst to avoid undefined ID
-    // error on validation.
-    // TODO: can moved below once sorting of types/consts/defs is implemented.
-    Register SpvScalConst;
-    if (!IsNull)
-      SpvScalConst =
-          getOrCreateBaseRegister(Val, I, SpvType, TII, BitWidth, ZeroAsNull);
-
-    LLT LLTy = LLT::scalar(64);
-    Register SpvVecConst =
-        CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
-    CurMF->getRegInfo().setRegClass(SpvVecConst, getRegClass(SpvType));
-    assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
-    DT.add(CA, CurMF, SpvVecConst);
-    MachineIRBuilder MIRBuilder(I);
-    createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-      MachineInstrBuilder MIB;
-      if (!IsNull) {
-        MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
-                  .addDef(SpvVecConst)
-                  .addUse(getSPIRVTypeID(SpvType));
-        for (unsigned i = 0; i < ElemCnt; ++i)
-          MIB.addUse(SpvScalConst);
-      } else {
-        MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
-                  .addDef(SpvVecConst)
-                  .addUse(getSPIRVTypeID(SpvType));
-      }
-      const auto &Subtarget = CurMF->getSubtarget();
-      constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
-                                       *Subtarget.getRegisterInfo(),
-                                       *Subtarget.getRegBankInfo());
-      return MIB;
-    });
-    return SpvVecConst;
-  }
+  Register ElemReg;
+  if (!IsNull)
+    ElemReg =
+        getOrCreateBaseRegister(Val, I, SpvType, TII, BitWidth, ZeroAsNull);
+
+  LLT LLTy = LLT::scalar(64);
+  Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
+  CurMF->getRegInfo().setRegClass(Res, getRegClass(SpvType));
+  assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
+
+  MachineIRBuilder MIRBuilder(I);
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        MachineInstrBuilder MIB;
+        if (!IsNull) {
+          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
+                    .addDef(Res)
+                    .addUse(getSPIRVTypeID(SpvType));
+          for (unsigned i = 0; i < ElemCnt; ++i)
+            MIB.addUse(ElemReg);
+        } else {
+          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
+                    .addDef(Res)
+                    .addUse(getSPIRVTypeID(SpvType));
+        }
+        const auto &Subtarget = CurMF->getSubtarget();
+        constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
+                                         *Subtarget.getRegisterInfo(),
+                                         *Subtarget.getRegBankInfo());
+        return MIB;
+      });
+  add(CA, NewMI);
   return Res;
 }
 
@@ -536,42 +531,38 @@ Register SPIRVGlobalRegistry::getOrCreateConstIntArray(
 Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
     uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
     Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
-  Register Res = DT.find(CA, CurMF);
-  if (!Res.isValid()) {
-    Register SpvScalConst;
-    if (Val || EmitIR) {
-      SPIRVType *SpvBaseType =
-          getOrCreateSPIRVIntegerType(BitWidth, MIRBuilder);
-      SpvScalConst = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
-    }
-    LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(64);
-    Register SpvVecConst =
-        CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
-    CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::iIDRegClass);
-    assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
-    DT.add(CA, CurMF, SpvVecConst);
-    if (EmitIR) {
-      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-        return MIRBuilder.buildSplatBuildVector(SpvVecConst, SpvScalConst);
-      });
-    } else {
+  if (Register R = find(CA, CurMF); R.isValid())
+    return R;
+
+  Register ElemReg;
+  if (Val || EmitIR) {
+    SPIRVType *SpvBaseType = getOrCreateSPIRVIntegerType(BitWidth, MIRBuilder);
+    ElemReg = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
+  }
+  LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(64);
+  Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
+  CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
+  assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
+
+  const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        if (EmitIR)
+          return MIRBuilder.buildSplatBuildVector(Res, ElemReg);
+
         if (Val) {
           auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
-                         .addDef(SpvVecConst)
+                         .addDef(Res)
                          .addUse(getSPIRVTypeID(SpvType));
           for (unsigned i = 0; i < ElemCnt; ++i)
-            MIB.addUse(SpvScalConst);
+            MIB.addUse(ElemReg);
           return MIB;
-        } else {
-          return MIRBuilder.buildInstr(SPIRV::OpConstantNull)
-              .addDef(SpvVecConst)
-              .addUse(getSPIRVTypeID(SpvType));
         }
+
+        return MIRBuilder.buildInstr(SPIRV::OpConstantNull)
+            .addDef(Res)
+            .addUse(getSPIRVTypeID(SpvType));
       });
-    }
-    return SpvVecConst;
-  }
+  add(CA, NewMI);
   return Res;
 }
 
@@ -595,24 +586,26 @@ SPIRVGlobalRegistry::getOrCreateConsIntVector(uint64_t Val,
 Register
 SPIRVGlobalRegistry::getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder,
                                              SPIRVType *SpvType) {
-  const Type *LLVMTy = getTypeForSPIRVType(SpvType);
-  unsigned AddressSpace = typeToAddressSpace(LLVMTy);
-  // Find a constant in DT or build a new one.
-  Constant *CP = ConstantPointerNull::get(
-      PointerType::get(LLVMTy->getContext(), AddressSpace));
-  Register Res = DT.find(CP, CurMF);
-  if (!Res.isValid()) {
-    LLT LLTy = LLT::pointer(AddressSpace, PointerSize);
-    Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
-    CurMF->getRegInfo().setRegClass(Res, &SPIRV::pIDRegClass);
-    assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
-    createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-      return MIRBuilder.buildInstr(SPIRV::OpConstantNull)
-          .addDef(Res)
-          .addUse(getSPIRVTypeID(SpvType));
-    });
-    DT.add(CP, CurMF, Res);
-  }
+  const Type *Ty = getTypeForSPIRVType(SpvType);
+  unsigned AddressSpace = typeToAddressSpace(Ty);
+  const Constant *CP = ConstantPointerNull::get(
+      PointerType::get(Ty->getContext(), AddressSpace));
+  Register Res = find(CP, CurMF);
+  if (Res.isValid())
+    return Res;
+
+  LLT LLTy = LLT::pointer(AddressSpace, PointerSize);
+  Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
+  CurMF->getRegInfo().setRegClass(Res, &SPIRV::pIDRegClass);
+  assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
+
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return MIRBuilder.buildInstr(SPIRV::OpConstantNull)
+            .addDef(Res)
+            .addUse(getSPIRVTypeID(SpvType));
+      });
+  add(CP, NewMI);
   return Res;
 }
 
@@ -620,7 +613,10 @@ Register
 SPIRVGlobalRegistry::buildConstantSampler(Register ResReg, unsigned AddrMode,
                                           unsigned Param, unsigned FilerMode,
                                           MachineIRBuilder &MIRBuilder) {
-  auto Sampler =
+      Register Res = find(CP, CurMF);
+      if (Res.isValid())
+        return Res;
+auto Sampler =
       ResReg.isValid()
           ? ResReg
           : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
@@ -1290,117 +1286,125 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeImage(
     uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
     SPIRV::ImageFormat::ImageFormat ImageFormat,
     SPIRV::AccessQualifier::AccessQualifier AccessQual) {
-  auto TD = SPIRV::make_descr_image(SPIRVToLLVMType.lookup(SampledType), Dim,
-                                    Depth, Arrayed, Multisampled, Sampled,
-                                    ImageFormat, AccessQual);
-  if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
-    return Res;
-  Register ResVReg = createTypeVReg(MIRBuilder);
-  DT.add(TD, &MIRBuilder.getMF(), ResVReg);
-  auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeImage)
-                 .addDef(ResVReg)
-                 .addUse(getSPIRVTypeID(SampledType))
-                 .addImm(Dim)
-                 .addImm(Depth)   // Depth (whether or not it is a Depth image).
-                 .addImm(Arrayed) // Arrayed.
-                 .addImm(Multisampled) // Multisampled (0 = only single-sample).
-                 .addImm(Sampled)      // Sampled (0 = usage known at runtime).
-                 .addImm(ImageFormat);
-
-  if (AccessQual != SPIRV::AccessQualifier::None)
-    MIB.addImm(AccessQual);
-  return MIB;
+  auto Key = SPIRV::make_descr_image(SPIRVToLLVMType.lookup(SampledType), Dim,
+                                     Depth, Arrayed, Multisampled, Sampled,
+                                     ImageFormat, AccessQual);
+  if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
+    return MI;
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        auto MIB =
+            MIRBuilder.buildInstr(SPIRV::OpTypeImage)
+                .addDef(createTypeVReg(MIRBuilder))
+                .addUse(getSPIRVTypeID(SampledType))
+                .addImm(Dim)
+                .addImm(Depth)   // Depth (whether or not it is a Depth image).
+                .addImm(Arrayed) // Arrayed.
+                .addImm(Multisampled) // Multisampled (0 = only single-sample).
+                .addImm(Sampled)      // Sampled (0 = usage known at runtime).
+                .addImm(ImageFormat);
+        if (AccessQual != SPIRV::AccessQualifier::None)
+          MIB.addImm(AccessQual);
+        return MIB;
+      });
+  add(Key, NewMI);
+  return NewMI;
 }
 
 SPIRVType *
 SPIRVGlobalRegistry::getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder) {
-  auto TD = SPIRV::make_descr_sampler();
-  if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
-    return Res;
-  Register ResVReg = createTypeVReg(MIRBuilder);
-  DT.add(TD, &MIRBuilder.getMF(), ResVReg);
-  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-    return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
-  });
+  auto Key = SPIRV::make_descr_sampler();
+  const MachineFunction *MF = &MIRBuilder.getMF();
+  if (const MachineInstr *MI = findMI(Key, MF))
+    return MI;
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return MIRBuilder.buildInstr(SPIRV::OpTypeSampler)
+            .addDef(createTypeVReg(MIRBuilder));
+      });
+  add(Key, NewMI);
+  return NewMI;
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypePipe(
     MachineIRBuilder &MIRBuilder,
     SPIRV::AccessQualifier::AccessQualifier AccessQual) {
-  auto TD = SPIRV::make_descr_pipe(AccessQual);
-  if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
-    return Res;
-  Register ResVReg = createTypeVReg(MIRBuilder);
-  DT.add(TD, &MIRBuilder.getMF(), ResVReg);
-  return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
-      .addDef(ResVReg)
-      .addImm(AccessQual);
+  auto Key = SPIRV::make_descr_pipe(AccessQual);
+  if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
+    return MI;
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
+            .addDef(createTypeVReg(MIRBuilder))
+            .addImm(AccessQual);
+      });
+  add(Key, NewMI);
+  return NewMI;
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeDeviceEvent(
     MachineIRBuilder &MIRBuilder) {
-  auto TD = SPIRV::make_descr_event();
-  if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
-    return Res;
-  Register ResVReg = createTypeVReg(MIRBuilder);
-  DT.add(TD, &MIRBuilder.getMF(), ResVReg);
-  return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent).addDef(ResVReg);
+  auto Key = SPIRV::make_descr_event();
+  if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
+    return MI;
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent)
+            .addDef(createTypeVReg(MIRBuilder));
+      });
+  add(Key, NewMI);
+  return NewMI;
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeSampledImage(
     SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
-  auto TD = SPIRV::make_descr_sampled_image(
+  auto Key = SPIRV::make_descr_sampled_image(
       SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
           ImageType->getOperand(1).getReg())),
       ImageType);
-  if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
-    return Res;
-  Register ResVReg = createTypeVReg(MIRBuilder);
-  DT.add(TD, &MIRBuilder.getMF(), ResVReg);
-  return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
-      .addDef(ResVReg)
-      .addUse(getSPIRVTypeID(ImageType));
+  if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
+    return MI;
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
+            .addDef(createTypeVReg(MIRBuilder))
+            .addUse(getSPIRVTypeID(ImageType));
+      });
+  add(Key, NewMI);
+  return NewMI;
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeCoopMatr(
     MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType,
     const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns,
     uint32_t Use, bool EmitIR) {
-  Register ResVReg = DT.find(ExtensionType, &MIRBuilder.getMF());
-  if (ResVReg.isValid())
-    return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
-  ResVReg = createTypeVReg(MIRBuilder);
-  SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, MIRBuilder);
-  SPIRVType *SpirvTy =
-      MIRBuilder.buildInstr(SPIRV::OpTypeCooperativeMatrixKHR)
-          .addDef(ResVReg)
-          .addUse(getSPIRVTypeID(ElemType))
-          .addUse(buildConstantInt(Scope, MIRBuilder, SpvTypeInt32, EmitIR))
-          .addUse(buildConstantInt(Rows, MIRBuilder, SpvTypeInt32, EmitIR))
-          .addUse(buildConstantInt(Columns, MIRBuilder, SpvTypeInt32, EmitIR))
-          .addUse(buildConstantInt(Use, MIRBuilder, SpvTypeInt32, EmitIR));
-  DT.add(ExtensionType, &MIRBuilder.getMF(), ResVReg);
-  return SpirvTy;
+  if (const MachineInstr *MI = findMI(ExtensionType, &MIRBuilder.getMF()))
+    return MI;
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, MIRBuilder);
+        return MIRBuilder.buildInstr(SPIRV::OpTypeCooperativeMatrixKHR)
+            .addDef(createTypeVReg(MIRBuilder))
+            .addUse(getSPIRVTypeID(ElemType))
+            .addUse(buildConstantInt(Scope, MIRBuilder, SpvTypeInt32, EmitIR))
+            .addUse(buildConstantInt(Rows, MIRBuilder, SpvTypeInt32, EmitIR))
+            .addUse(buildConstantInt(Columns, MIRBuilder, SpvTypeInt32, EmitIR))
+            .addUse(buildConstantInt(Use, MIRBuilder, SpvTypeInt32, EmitIR));
+      });
+  add(Key, NewMI);
+  return NewMI;
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeByOpcode(
     const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
-  Register ResVReg = DT.find(Ty, &MIRBuilder.getMF());
-  if (ResVReg.isValid())
-    return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
-  ResVReg = createTypeVReg(MIRBuilder);
-  SPIRVType *SpirvTy = MIRBuilder.buildInstr(Opcode).addDef(ResVReg);
-  DT.add(Ty, &MIRBuilder.getMF(), ResVReg);
-  return SpirvTy;
-}
-
-const MachineInstr *
-SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
-                                       MachineIRBuilder &MIRBuilder) {
-  Register Reg = DT.find(TD, &MIRBuilder.getMF());
-  if (Reg.isValid())
-    return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(Reg);
-  return nullptr;
+  if (const MachineInstr *MI = findMI(Ty, &MIRBuilder.getMF()))
+    return MI;
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return MIRBuilder.buildInstr(Opcode).addDef(createTypeVReg(MIRBuilder));
+      });
+  add(Key, NewMI);
+  return NewMI;
 }
 
 // Returns nullptr if unable to recognize SPIRV type name
@@ -1470,16 +1474,17 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(unsigned BitWidth,
                                                      MachineInstr &I,
                                                      const SPIRVInstrInfo &TII,
                                                      unsigned SPIRVOPcode,
-                                                     Type *LLVMTy) {
-  Register Reg = DT.find(LLVMTy, CurMF);
-  if (Reg.isValid())
-    return getSPIRVTypeForVReg(Reg);
-  MachineBasicBlock &BB = *I.getParent();
-  auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRVOPcode))
-                 .addDef(createTypeVReg(CurMF->getRegInfo()))
-                 .addImm(BitWidth)
-                 .addImm(0);
-  DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
+                                                     Type *Ty) {
+  if (const MachineInstr *MI = findMI(Ty, CurMF))
+    return MI;
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRVOPcode))
+            .addDef(createTypeVReg(CurMF->getRegInfo()))
+            .addImm(BitWidth)
+            .addImm(0);
+      });
+  add(LLVMTy, NewMI);
   return finishCreatingSPIRVType(LLVMTy, MIB);
 }
 

>From 1ab3c988c266a834074d227ebef17829cb47aff7 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Tue, 11 Mar 2025 05:39:47 -0700
Subject: [PATCH 5/9] a new duplicate tracker

---
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h            | 10 ++--------
 .../{SPIRVDuplicatesTracker.h => SPIRVIRMapping.h}     |  8 ++++----
 2 files changed, 6 insertions(+), 12 deletions(-)
 rename llvm/lib/Target/SPIRV/{SPIRVDuplicatesTracker.h => SPIRVIRMapping.h} (96%)

diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index 8840401fe996d..6c2f08e315e3a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -17,7 +17,7 @@
 #define LLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H
 
 #include "MCTargetDesc/SPIRVBaseInfo.h"
-#include "SPIRVDuplicatesTracker.h"
+#include "SPIRVIRMapping.h"
 #include "SPIRVInstrInfo.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/IR/Constant.h"
@@ -27,7 +27,7 @@ namespace llvm {
 class SPIRVSubtarget;
 using SPIRVType = const MachineInstr;
 
-class SPIRVGlobalRegistry : public SPIRVIRMap {
+class SPIRVGlobalRegistry : public SPIRVIRMapping {
   // Registers holding values which have types associated with them.
   // Initialized upon VReg definition in IRTranslator.
   // Do not confuse this with DuplicatesTracker as DT maps Type* to <MF, Reg>
@@ -454,12 +454,6 @@ class SPIRVGlobalRegistry : public SPIRVIRMap {
   getOrCreateSpecialType(const Type *Ty, MachineIRBuilder &MIRBuilder,
                          SPIRV::AccessQualifier::AccessQualifier AccQual);
 
-  std::tuple<Register, ConstantInt *, bool, unsigned> getOrCreateConstIntReg(
-      uint64_t Val, SPIRVType *SpvType, MachineIRBuilder *MIRBuilder,
-      MachineInstr *I = nullptr, const SPIRVInstrInfo *TII = nullptr);
-  std::tuple<Register, ConstantFP *, bool, unsigned> getOrCreateConstFloatReg(
-      APFloat Val, SPIRVType *SpvType, MachineIRBuilder *MIRBuilder,
-      MachineInstr *I = nullptr, const SPIRVInstrInfo *TII = nullptr);
   SPIRVType *finishCreatingSPIRVType(const Type *LLVMTy, SPIRVType *SpirvType);
   Register getOrCreateBaseRegister(Constant *Val, MachineInstr &I,
                                    SPIRVType *SpvType,
diff --git a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h b/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
similarity index 96%
rename from llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
rename to llvm/lib/Target/SPIRV/SPIRVIRMapping.h
index aa3171f3e7d10..248384e50eac1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
+++ b/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H
-#define LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVIRMAPPING_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVIRMAPPING_H
 
 #include "MCTargetDesc/SPIRVBaseInfo.h"
 #include "MCTargetDesc/SPIRVMCTargetDesc.h"
@@ -118,7 +118,7 @@ inline IRHandle make_descr_ptr(const void *Ptr) {
 // Bi-directional mappings between LLVM entities and (v-reg, machine function)
 // pairs support management of unique SPIR-V definitions per machine function
 // per an LLVM/GlobalISel entity (e.g., Type, Constant, Machine Instruction).
-class SPIRVIRMap {
+class SPIRVIRMapping {
   DenseMap < std::pair<IRHandle, const MachineFunction *>,
       const MachineInstr *MI >> Vregs;
   DenseMap<const MachineInstr *, IRHandle> Defs;
@@ -176,4 +176,4 @@ class SPIRVIRMap {
   }
 };
 } // namespace llvm
-#endif // LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVIRMAPPING_H

>From 27285488b0d8e25cc3e29b623d77a29e1b172917 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Tue, 11 Mar 2025 07:03:18 -0700
Subject: [PATCH 6/9] a new duplicate tracker

---
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 299 +++++++++---------
 llvm/lib/Target/SPIRV/SPIRVIRMapping.h        |   4 +-
 2 files changed, 148 insertions(+), 155 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index c0735f380f82b..69d707ca2ec15 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -613,23 +613,22 @@ Register
 SPIRVGlobalRegistry::buildConstantSampler(Register ResReg, unsigned AddrMode,
                                           unsigned Param, unsigned FilerMode,
                                           MachineIRBuilder &MIRBuilder) {
-      Register Res = find(CP, CurMF);
-      if (Res.isValid())
-        return Res;
-auto Sampler =
+  auto Sampler =
       ResReg.isValid()
           ? ResReg
           : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
-  auto Res = createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-    return MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
-        .addDef(Sampler)
-        .addUse(getSPIRVTypeID(getOrCreateOpTypeSampler(MIRBuilder)))
-        .addImm(AddrMode)
-        .addImm(Param)
-        .addImm(FilerMode);
-  });
-  assert(Res->getOperand(0).isReg());
-  return Res->getOperand(0).getReg();
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
+            .addDef(Sampler)
+            .addUse(getSPIRVTypeID(getOrCreateOpTypeSampler(MIRBuilder)))
+            .addImm(AddrMode)
+            .addImm(Param)
+            .addImm(FilerMode);
+      });
+  // TODO: this is a constant and it needs a usual control flow of add()/find()
+  // as other constants
+  return NewMI->getOperand(0).getReg();
 }
 
 Register SPIRVGlobalRegistry::buildGlobalVariable(
@@ -639,9 +638,9 @@ Register SPIRVGlobalRegistry::buildGlobalVariable(
     SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder,
     bool IsInstSelector) {
   const GlobalVariable *GVar = nullptr;
-  if (GV)
+  if (GV) {
     GVar = cast<const GlobalVariable>(GV);
-  else {
+  } else {
     // If GV is not passed explicitly, use the name to find or construct
     // the global variable.
     Module *M = MIRBuilder.getMF().getFunction().getParent();
@@ -655,7 +654,9 @@ Register SPIRVGlobalRegistry::buildGlobalVariable(
     }
     GV = GVar;
   }
-  Register Reg = DT.find(GVar, &MIRBuilder.getMF());
+
+  const MachineFunction *MF = &MIRBuilder.getMF();
+  Register Reg = find(GVar, MF);
   if (Reg.isValid()) {
     if (Reg != ResVReg)
       MIRBuilder.buildCopy(ResVReg, Reg);
@@ -666,11 +667,8 @@ Register SPIRVGlobalRegistry::buildGlobalVariable(
                  .addDef(ResVReg)
                  .addUse(getSPIRVTypeID(BaseType))
                  .addImm(static_cast<uint32_t>(Storage));
-
-  if (Init != 0) {
+  if (Init != 0)
     MIB.addUse(Init->getOperand(0).getReg());
-  }
-
   // ISel may introduce a new register on this step, so we need to add it to
   // DT and correct its type avoiding fails on the next stage.
   if (IsInstSelector) {
@@ -679,9 +677,10 @@ Register SPIRVGlobalRegistry::buildGlobalVariable(
                                      *Subtarget.getRegisterInfo(),
                                      *Subtarget.getRegBankInfo());
   }
+  add(GVar, MIB);
+
   Reg = MIB->getOperand(0).getReg();
-  DT.add(GVar, &MIRBuilder.getMF(), Reg);
-  addGlobalObject(GVar, &MIRBuilder.getMF(), Reg);
+  addGlobalObject(GVar, MF, Reg);
 
   // Set to Reg the same type as ResVReg has.
   auto MRI = MIRBuilder.getMRI();
@@ -866,23 +865,18 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(
   if (Ty->isPacked())
     buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
 
-  auto SPVType = createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-    auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
+  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+    auto MIBStruct = MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
     for (size_t I = 0; I < SPIRVStructNumElements; ++I)
-      MIB.addUse(FieldTypes[I]);
-    return MIB;
-  });
-
-  for (size_t I = SPIRVStructNumElements; I < NumElements;
-       I += MaxNumElements) {
-    createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-      auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeStructContinuedINTEL);
+      MIBStruct.addUse(FieldTypes[I]);
+    for (size_t I = SPIRVStructNumElements; I < NumElements;
+         I += MaxNumElements) {
+      auto MIBCont = MIRBuilder.buildInstr(SPIRV::OpTypeStructContinuedINTEL);
       for (size_t J = I; J < std::min(I + MaxNumElements, NumElements); ++J)
-        MIB.addUse(FieldTypes[I]);
-      return MIB;
-    });
-  }
-  return SPVType;
+        MIBCont.addUse(FieldTypes[I]);
+    }
+    return MIBStruct;
+  });
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
@@ -918,33 +912,33 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
 SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
     SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
     MachineIRBuilder &MIRBuilder) {
-  auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
-                 .addDef(createTypeVReg(MIRBuilder))
-                 .addUse(getSPIRVTypeID(RetType));
-  for (const SPIRVType *ArgType : ArgTypes)
-    MIB.addUse(getSPIRVTypeID(ArgType));
-  return MIB;
+  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+    auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
+                   .addDef(createTypeVReg(MIRBuilder))
+                   .addUse(getSPIRVTypeID(RetType));
+    for (const SPIRVType *ArgType : ArgTypes)
+      MIB.addUse(getSPIRVTypeID(ArgType));
+    return MIB;
+  });
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeFunctionWithArgs(
     const Type *Ty, SPIRVType *RetType,
     const SmallVectorImpl<SPIRVType *> &ArgTypes,
     MachineIRBuilder &MIRBuilder) {
-  Register Reg = DT.find(Ty, &MIRBuilder.getMF());
-  if (Reg.isValid())
-    return getSPIRVTypeForVReg(Reg);
-  SPIRVType *SpirvType = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
-  DT.add(Ty, CurMF, getSPIRVTypeID(SpirvType));
-  return finishCreatingSPIRVType(Ty, SpirvType);
+  if (const MachineInstr *MI = findMI(Ty, &MIRBuilder.getMF()))
+    return MI;
+  const MachineInstr *NewMI = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
+  add(Ty, NewMI);
+  return finishCreatingSPIRVType(Ty, NewMI);
 }
 
 SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
     const Type *Ty, MachineIRBuilder &MIRBuilder,
     SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
   Ty = adjustIntTypeByWidth(Ty);
-  Register Reg = DT.find(Ty, &MIRBuilder.getMF());
-  if (Reg.isValid())
-    return getSPIRVTypeForVReg(Reg);
+  if (const MachineInstr *MI = findMI(Ty, &MIRBuilder.getMF()))
+    return MI;
   if (auto It = ForwardPointerTypes.find(Ty); It != ForwardPointerTypes.end())
     return It->second;
   return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, EmitIR);
@@ -984,8 +978,9 @@ SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
     SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
   if (isSpecialOpaqueType(Ty))
     return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
-  if (Register TyReg = DT.find(Ty, &MIRBuilder.getMF()); TyReg.isValid())
-    return getSPIRVTypeForVReg(TyReg);
+
+  if (const MachineInstr *MI = findMI(Ty, &MIRBuilder.getMF()))
+    return MI;
 
   if (auto IType = dyn_cast<IntegerType>(Ty)) {
     const unsigned Width = IType->getBitWidth();
@@ -1060,27 +1055,22 @@ SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
   TypesInProcessing.erase(Ty);
   VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
   SPIRVToLLVMType[SpirvType] = unifyPtrType(Ty);
-  Register Reg = DT.find(Ty, &MIRBuilder.getMF());
-  // Do not add OpTypeForwardPointer to DT, a corresponding normal pointer type
-  // will be added later. For special types it is already added to DT.
-  if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() &&
-      !isSpecialOpaqueType(Ty)) {
-    if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
-        ExtTy && isTypedPointerWrapper(ExtTy))
-      DT.add(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0),
-             &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
-    else if (!isPointerTy(Ty))
-      DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
-    else if (isTypedPointerTy(Ty))
-      DT.add(cast<TypedPointerType>(Ty)->getElementType(),
-             getPointerAddressSpace(Ty), &MIRBuilder.getMF(),
-             getSPIRVTypeID(SpirvType));
-    else
-      DT.add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
-             getPointerAddressSpace(Ty), &MIRBuilder.getMF(),
-             getSPIRVTypeID(SpirvType));
-  }
 
+  if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer ||
+      findMI(Ty, &MIRBuilder.getMF()) || isSpecialOpaqueType(Ty))
+    return SpirvType;
+
+  if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
+      ExtTy && isTypedPointerWrapper(ExtTy))
+    add(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0), SpirvType);
+  else if (!isPointerTy(Ty))
+    add(Ty, SpirvType);
+  else if (isTypedPointerTy(Ty))
+    add(cast<TypedPointerType>(Ty)->getElementType(),
+        getPointerAddressSpace(Ty), SpirvType);
+  else
+    add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
+        getPointerAddressSpace(Ty), SpirvType);
   return SpirvType;
 }
 
@@ -1107,32 +1097,29 @@ SPIRVType *SPIRVGlobalRegistry::getResultType(Register VReg,
 SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(
     const Type *Ty, MachineIRBuilder &MIRBuilder,
     SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
+  const MachineFunction *MF = &MIRBuilder.getMF();
   Register Reg;
   if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
-      ExtTy && isTypedPointerWrapper(ExtTy)) {
-    Reg = DT.find(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0),
-                  &MIRBuilder.getMF());
-  } else if (!isPointerTy(Ty)) {
-    Ty = adjustIntTypeByWidth(Ty);
-    Reg = DT.find(Ty, &MIRBuilder.getMF());
-  } else if (isTypedPointerTy(Ty)) {
-    Reg = DT.find(cast<TypedPointerType>(Ty)->getElementType(),
-                  getPointerAddressSpace(Ty), &MIRBuilder.getMF());
-  } else {
-    Reg =
-        DT.find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
-                getPointerAddressSpace(Ty), &MIRBuilder.getMF());
-  }
-
+      ExtTy && isTypedPointerWrapper(ExtTy))
+    Reg = find(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0), MF);
+  else if (!isPointerTy(Ty))
+    Reg = find(Ty = adjustIntTypeByWidth(Ty), MF);
+  else if (isTypedPointerTy(Ty))
+    Reg = find(cast<TypedPointerType>(Ty)->getElementType(),
+               getPointerAddressSpace(Ty), MF);
+  else
+    Reg = find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
+               getPointerAddressSpace(Ty), MF);
   if (Reg.isValid() && !isSpecialOpaqueType(Ty))
     return getSPIRVTypeForVReg(Reg);
+
   TypesInProcessing.clear();
   SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
   // Create normal pointer types for the corresponding OpTypeForwardPointers.
   for (auto &CU : ForwardPointerTypes) {
     const Type *Ty2 = CU.first;
     SPIRVType *STy2 = CU.second;
-    if ((Reg = DT.find(Ty2, &MIRBuilder.getMF())).isValid())
+    if ((Reg = find(Ty2, MF)).isValid())
       STy2 = getSPIRVTypeForVReg(Reg);
     else
       STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, EmitIR);
@@ -1530,15 +1517,17 @@ SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder,
 SPIRVType *
 SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineInstr &I,
                                               const SPIRVInstrInfo &TII) {
-  Type *LLVMTy = IntegerType::get(CurMF->getFunction().getContext(), 1);
-  Register Reg = DT.find(LLVMTy, CurMF);
-  if (Reg.isValid())
-    return getSPIRVTypeForVReg(Reg);
-  MachineBasicBlock &BB = *I.getParent();
-  auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeBool))
-                 .addDef(createTypeVReg(CurMF->getRegInfo()));
-  DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
-  return finishCreatingSPIRVType(LLVMTy, MIB);
+  Type *Ty = IntegerType::get(CurMF->getFunction().getContext(), 1);
+  if (const MachineInstr *MI = findMI(Ty, CurMF))
+    return MI;
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return BuildMI(*I.getParent(), I, I.getDebugLoc(),
+                       TII.get(SPIRV::OpTypeBool))
+            .addDef(createTypeVReg(CurMF->getRegInfo()));
+      });
+  add(Ty, NewMI);
+  return finishCreatingSPIRVType(Ty, NewMI);
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
@@ -1553,37 +1542,41 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
 SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
     SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
     const SPIRVInstrInfo &TII) {
-  Type *LLVMTy = FixedVectorType::get(
+  Type *Ty = FixedVectorType::get(
       const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
-  Register Reg = DT.find(LLVMTy, CurMF);
-  if (Reg.isValid())
-    return getSPIRVTypeForVReg(Reg);
-  MachineBasicBlock &BB = *I.getParent();
-  auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeVector))
-                 .addDef(createTypeVReg(CurMF->getRegInfo()))
-                 .addUse(getSPIRVTypeID(BaseType))
-                 .addImm(NumElements);
-  DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
-  return finishCreatingSPIRVType(LLVMTy, MIB);
+  if (const MachineInstr *MI = findMI(Ty, CurMF))
+    return MI;
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return BuildMI(*I.getParent(), I, I.getDebugLoc(),
+                       TII.get(SPIRV::OpTypeVector))
+            .addDef(createTypeVReg(CurMF->getRegInfo()))
+            .addUse(getSPIRVTypeID(BaseType))
+            .addImm(NumElements);
+      });
+  add(Ty, NewMI);
+  return finishCreatingSPIRVType(Ty, NewMI);
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVArrayType(
     SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
     const SPIRVInstrInfo &TII) {
-  Type *LLVMTy = ArrayType::get(
-      const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
-  Register Reg = DT.find(LLVMTy, CurMF);
-  if (Reg.isValid())
-    return getSPIRVTypeForVReg(Reg);
-  MachineBasicBlock &BB = *I.getParent();
+  Type *Ty = ArrayType::get(const_cast<Type *>(getTypeForSPIRVType(BaseType)),
+                            NumElements);
+  if (const MachineInstr *MI = findMI(Ty, CurMF))
+    return MI;
   SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, I, TII);
   Register Len = getOrCreateConstInt(NumElements, I, SpvTypeInt32, TII);
-  auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeArray))
-                 .addDef(createTypeVReg(CurMF->getRegInfo()))
-                 .addUse(getSPIRVTypeID(BaseType))
-                 .addUse(Len);
-  DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
-  return finishCreatingSPIRVType(LLVMTy, MIB);
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return BuildMI(*I.getParent(), I, I.getDebugLoc(),
+                       TII.get(SPIRV::OpTypeArray))
+            .addDef(createTypeVReg(CurMF->getRegInfo()))
+            .addUse(getSPIRVTypeID(BaseType))
+            .addUse(Len);
+      });
+  add(Ty, NewMI);
+  return finishCreatingSPIRVType(Ty, NewMI);
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
@@ -1591,24 +1584,21 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
     SPIRV::StorageClass::StorageClass SC) {
   const Type *PointerElementType = getTypeForSPIRVType(BaseType);
   unsigned AddressSpace = storageClassToAddressSpace(SC);
-  Type *LLVMTy = TypedPointerType::get(const_cast<Type *>(PointerElementType),
-                                       AddressSpace);
-  // check if this type is already available
-  Register Reg = DT.find(PointerElementType, AddressSpace, CurMF);
-  if (Reg.isValid())
-    return getSPIRVTypeForVReg(Reg);
-  // create a new type
-  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-    auto MIB = BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),
+  if (const MachineInstr *MI = findMI(PointerElementType, AddressSpace, CurMF))
+    return MI;
+  Type *Ty = TypedPointerType::get(const_cast<Type *>(PointerElementType),
+                                   AddressSpace);
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        return BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),
                        MIRBuilder.getDebugLoc(),
                        MIRBuilder.getTII().get(SPIRV::OpTypePointer))
-                   .addDef(createTypeVReg(CurMF->getRegInfo()))
-                   .addImm(static_cast<uint32_t>(SC))
-                   .addUse(getSPIRVTypeID(BaseType));
-    DT.add(PointerElementType, AddressSpace, CurMF, getSPIRVTypeID(MIB));
-    finishCreatingSPIRVType(LLVMTy, MIB);
-    return MIB;
-  });
+            .addDef(createTypeVReg(CurMF->getRegInfo()))
+            .addImm(static_cast<uint32_t>(SC))
+            .addUse(getSPIRVTypeID(BaseType));
+      });
+  add(PointerElementType, AddressSpace, NewMI);
+  return finishCreatingSPIRVType(Ty, MIB);
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
@@ -1621,27 +1611,30 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
 Register SPIRVGlobalRegistry::getOrCreateUndef(MachineInstr &I,
                                                SPIRVType *SpvType,
                                                const SPIRVInstrInfo &TII) {
-  assert(SpvType);
-  const Type *LLVMTy = getTypeForSPIRVType(SpvType);
-  assert(LLVMTy);
-  // Find a constant in DT or build a new one.
-  UndefValue *UV = UndefValue::get(const_cast<Type *>(LLVMTy));
-  Register Res = DT.find(UV, CurMF);
+  UndefValue *UV =
+      UndefValue::get(const_cast<Type *>(getTypeForSPIRVType(SpvType)));
+  Register Res = find(UV, CurMF);
   if (Res.isValid())
     return Res;
+
   LLT LLTy = LLT::scalar(64);
   Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
   CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
   assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
-  DT.add(UV, CurMF, Res);
 
-  MachineInstrBuilder MIB;
-  MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
-            .addDef(Res)
-            .addUse(getSPIRVTypeID(SpvType));
-  const auto &ST = CurMF->getSubtarget();
-  constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
-                                   *ST.getRegisterInfo(), *ST.getRegBankInfo());
+  const MachineInstr *NewMI =
+      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
+        auto MIB =
+            BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
+                .addDef(Res)
+                .addUse(getSPIRVTypeID(SpvType));
+        const auto &ST = CurMF->getSubtarget();
+        constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
+                                         *ST.getRegisterInfo(),
+                                         *ST.getRegBankInfo());
+        return MIB;
+      });
+  add(UV, NewMI);
   return Res;
 }
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVIRMapping.h b/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
index 248384e50eac1..a70fde0a9ffc0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
+++ b/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
@@ -110,8 +110,8 @@ inline IRHandle make_descr_pointee(const Type *ElementType,
                          SpecialTypeKind::STK_ElementPointer);
 }
 
-inline IRHandle make_descr_ptr(const void *Ptr) {
-  return std::make_tuple(Ptr, 0U, SpecialTypeKind::STK_Pointer);
+inline IRHandle make_descr_ptr(const void *Ptr, unsigned Arg = 0U) {
+  return std::make_tuple(Ptr, Arg, SpecialTypeKind::STK_Pointer);
 }
 } // namespace SPIRV
 

>From d577b10229d45f3f085df0ecb0d1e0ded85dd7b0 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Tue, 11 Mar 2025 07:54:33 -0700
Subject: [PATCH 7/9] a new duplicate tracker

---
 llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp   | 12 ++--
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp |  8 +--
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 30 +++++----
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h   |  5 --
 llvm/lib/Target/SPIRV/SPIRVIRMapping.h        | 29 ++++++---
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 65 ++++++++++---------
 llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp   | 22 +++----
 7 files changed, 93 insertions(+), 78 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
index 3039f975a4df2..d55631e0146cf 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
@@ -398,8 +398,6 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
   auto MRI = MIRBuilder.getMRI();
   Register FuncVReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
   MRI->setRegClass(FuncVReg, &SPIRV::iIDRegClass);
-  if (F.isDeclaration())
-    GR->add(&F, &MIRBuilder.getMF(), FuncVReg);
   FunctionType *FTy = getOriginalFunctionType(F);
   Type *FRetTy = FTy->getReturnType();
   if (isUntypedPointerTy(FRetTy)) {
@@ -425,6 +423,8 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
                                .addUse(GR->getSPIRVTypeID(FuncTy));
   GR->recordFunctionDefinition(&F, &MB.getInstr()->getOperand(0));
   GR->addGlobalObject(&F, &MIRBuilder.getMF(), FuncVReg);
+  if (F.isDeclaration())
+    GR->add(&F, MB);
 
   // Add OpFunctionParameter instructions
   int i = 0;
@@ -433,11 +433,11 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
     Register ArgReg = VRegs[i][0];
     MRI->setRegClass(ArgReg, GR->getRegClass(ArgTypeVRegs[i]));
     MRI->setType(ArgReg, GR->getRegType(ArgTypeVRegs[i]));
-    MIRBuilder.buildInstr(SPIRV::OpFunctionParameter)
-        .addDef(ArgReg)
-        .addUse(GR->getSPIRVTypeID(ArgTypeVRegs[i]));
+    auto MIB = MIRBuilder.buildInstr(SPIRV::OpFunctionParameter)
+                   .addDef(ArgReg)
+                   .addUse(GR->getSPIRVTypeID(ArgTypeVRegs[i]));
     if (F.isDeclaration())
-      GR->add(&Arg, &MIRBuilder.getMF(), ArgReg);
+      GR->add(&Arg, MIB);
     GR->addGlobalObject(&Arg, &MIRBuilder.getMF(), ArgReg);
     i++;
   }
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 356f4f6dab75c..cd01d158cc861 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -63,7 +63,7 @@ class SPIRVEmitIntrinsics
   SPIRVTargetMachine *TM = nullptr;
   SPIRVGlobalRegistry *GR = nullptr;
   Function *CurrF = nullptr;
-  bool TrackConstants = false;//true;
+  bool TrackConstants = true;
   bool HaveFunPtrs = false;
   DenseMap<Instruction *, Constant *> AggrConsts;
   DenseMap<Instruction *, Type *> AggrConstTypes;
@@ -2025,7 +2025,7 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
   auto *II = dyn_cast<IntrinsicInst>(I);
   bool IsConstComposite =
       II && II->getIntrinsicID() == Intrinsic::spv_const_composite;
-  if (IsConstComposite) {
+  if (IsConstComposite && TrackConstants) {
     setInsertPointAfterDef(B, I);
     auto t = AggrConsts.find(I);
     assert(t != AggrConsts.end());
@@ -2042,7 +2042,7 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
       continue;
     unsigned OpNo = Op.getOperandNo();
     if (II && ((II->getIntrinsicID() == Intrinsic::spv_gep && OpNo == 0) ||
-                (II->paramHasAttr(OpNo, Attribute::ImmArg))))
+               (II->paramHasAttr(OpNo, Attribute::ImmArg))))
       continue;
 
     if (!BPrepared) {
@@ -2421,7 +2421,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
         deduceOperandElementType(&Phi, nullptr);
 
   for (auto *I : Worklist) {
-    TrackConstants = false;//true;
+    TrackConstants = true;
     if (!I->getType()->isVoidTy() || isa<StoreInst>(I))
       setInsertPointAfterDef(B, I);
     // Visitors return either the original/newly created instruction for further
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 69d707ca2ec15..62e4d50b1926a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -178,7 +178,6 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
 
 void SPIRVGlobalRegistry::invalidateMachineInstr(MachineInstr *MI) {
   // TODO:
-  // - take into account duplicate tracker case which is a known issue,
   // - review other data structure wrt. possible issues related to removal
   //   of a machine instruction during instruction selection.
   const MachineFunction *MF = MI->getMF();
@@ -187,6 +186,8 @@ void SPIRVGlobalRegistry::invalidateMachineInstr(MachineInstr *MI) {
     return;
   if (It->second == MI)
     LastInsertedTypeMap.erase(MF);
+  // remove from the duplicate tracker to avoid incorrect reuse
+  erase(MI);
 }
 
 SPIRVType *SPIRVGlobalRegistry::createOpType(
@@ -275,7 +276,7 @@ Register SPIRVGlobalRegistry::getOrCreateConstFP(APFloat Val, MachineInstr &I,
                     .addDef(Res)
                     .addUse(getSPIRVTypeID(SpvType));
           addNumImm(APInt(BitWidth,
-                          CI->getValueAPF().bitcastToAPInt().getZExtValue()),
+                          CF->getValueAPF().bitcastToAPInt().getZExtValue()),
                     MIB);
         }
         const auto &ST = CurMF->getSubtarget();
@@ -284,7 +285,7 @@ Register SPIRVGlobalRegistry::getOrCreateConstFP(APFloat Val, MachineInstr &I,
                                          *ST.getRegBankInfo());
         return MIB;
       });
-  add(CI, NewType);
+  add(CF, NewType);
   return Res;
 }
 
@@ -367,7 +368,7 @@ Register SPIRVGlobalRegistry::buildConstantInt(uint64_t Val,
                                          *Subtarget.getRegBankInfo());
         return MIB;
       });
-  add(ConstInt, NewType);
+  add(CI, NewType);
   return Res;
 }
 
@@ -375,10 +376,10 @@ Register SPIRVGlobalRegistry::buildConstantFP(APFloat Val,
                                               MachineIRBuilder &MIRBuilder,
                                               SPIRVType *SpvType) {
   auto &MF = MIRBuilder.getMF();
+  LLVMContext &Ctx = MF.getFunction().getContext();
   if (!SpvType)
-    SpvType = getOrCreateSPIRVType(
-        Type::getFloatTy(MF.getFunction().getContext()), MIRBuilder,
-        SPIRV::AccessQualifier::ReadWrite, true);
+    SpvType = getOrCreateSPIRVType(Type::getFloatTy(Ctx), MIRBuilder,
+                                   SPIRV::AccessQualifier::ReadWrite, true);
   auto *const CF = ConstantFP::get(Ctx, Val);
   Register Res = find(CF, &MF);
   if (Res.isValid())
@@ -1378,7 +1379,7 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeCoopMatr(
             .addUse(buildConstantInt(Columns, MIRBuilder, SpvTypeInt32, EmitIR))
             .addUse(buildConstantInt(Use, MIRBuilder, SpvTypeInt32, EmitIR));
       });
-  add(Key, NewMI);
+  add(ExtensionType, NewMI);
   return NewMI;
 }
 
@@ -1390,7 +1391,7 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeByOpcode(
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
         return MIRBuilder.buildInstr(Opcode).addDef(createTypeVReg(MIRBuilder));
       });
-  add(Key, NewMI);
+  add(Ty, NewMI);
   return NewMI;
 }
 
@@ -1464,6 +1465,7 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(unsigned BitWidth,
                                                      Type *Ty) {
   if (const MachineInstr *MI = findMI(Ty, CurMF))
     return MI;
+  MachineIRBuilder MIRBuilder(I);
   const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
         return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRVOPcode))
@@ -1471,8 +1473,8 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(unsigned BitWidth,
             .addImm(BitWidth)
             .addImm(0);
       });
-  add(LLVMTy, NewMI);
-  return finishCreatingSPIRVType(LLVMTy, MIB);
+  add(Ty, NewMI);
+  return finishCreatingSPIRVType(Ty, NewMI);
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVIntegerType(
@@ -1520,6 +1522,7 @@ SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineInstr &I,
   Type *Ty = IntegerType::get(CurMF->getFunction().getContext(), 1);
   if (const MachineInstr *MI = findMI(Ty, CurMF))
     return MI;
+  MachineIRBuilder MIRBuilder(I);
   const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
         return BuildMI(*I.getParent(), I, I.getDebugLoc(),
@@ -1546,6 +1549,7 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
       const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
   if (const MachineInstr *MI = findMI(Ty, CurMF))
     return MI;
+  MachineIRBuilder MIRBuilder(I);
   const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
         return BuildMI(*I.getParent(), I, I.getDebugLoc(),
@@ -1567,6 +1571,7 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVArrayType(
     return MI;
   SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, I, TII);
   Register Len = getOrCreateConstInt(NumElements, I, SpvTypeInt32, TII);
+  MachineIRBuilder MIRBuilder(I);
   const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
         return BuildMI(*I.getParent(), I, I.getDebugLoc(),
@@ -1598,7 +1603,7 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
             .addUse(getSPIRVTypeID(BaseType));
       });
   add(PointerElementType, AddressSpace, NewMI);
-  return finishCreatingSPIRVType(Ty, MIB);
+  return finishCreatingSPIRVType(Ty, NewMI);
 }
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
@@ -1622,6 +1627,7 @@ Register SPIRVGlobalRegistry::getOrCreateUndef(MachineInstr &I,
   CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
   assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
 
+  MachineIRBuilder MIRBuilder(I);
   const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
         auto MIB =
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index 6c2f08e315e3a..3c6c11fae92b3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -55,11 +55,6 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
   // map an instruction to its value's attributes (type, name)
   DenseMap<MachineInstr *, std::pair<Type *, std::string>> ValueAttrs;
 
-  // Look for an equivalent of the newType in the map. Return the equivalent
-  // if it's found, otherwise insert newType to the map and return the type.
-  const MachineInstr *checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
-                                        MachineIRBuilder &MIRBuilder);
-
   SmallPtrSet<const Type *, 4> TypesInProcessing;
   DenseMap<const Type *, SPIRVType *> ForwardPointerTypes;
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVIRMapping.h b/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
index a70fde0a9ffc0..8f1a345565630 100644
--- a/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
+++ b/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
@@ -119,19 +119,20 @@ inline IRHandle make_descr_ptr(const void *Ptr, unsigned Arg = 0U) {
 // pairs support management of unique SPIR-V definitions per machine function
 // per an LLVM/GlobalISel entity (e.g., Type, Constant, Machine Instruction).
 class SPIRVIRMapping {
-  DenseMap < std::pair<IRHandle, const MachineFunction *>,
-      const MachineInstr *MI >> Vregs;
-  DenseMap<const MachineInstr *, IRHandle> Defs;
+  DenseMap<std::pair<SPIRV::IRHandle, const MachineFunction *>,
+           const MachineInstr *>
+      Vregs;
+  DenseMap<const MachineInstr *, SPIRV::IRHandle> Defs;
 
 public:
-  bool add(IRHandle Handle, const MachineInstr *MI) {
+  bool add(SPIRV::IRHandle Handle, const MachineInstr *MI) {
     auto [It, Inserted] =
         Vregs.try_emplace(std::make_pair(Handle, MI->getMF()), MI);
     if (Inserted) {
       auto [_, IsConsistent] = Defs.insert_or_assign(MI, Handle);
       assert(IsConsistent);
     }
-    return Inserted1;
+    return Inserted;
   }
   bool erase(const MachineInstr *MI) {
     bool Res = false;
@@ -141,12 +142,13 @@ class SPIRVIRMapping {
     }
     return Res;
   }
-  const MachineInstr *findMI(IRHandle Handle, const MachineFunction *MF) {
+  const MachineInstr *findMI(SPIRV::IRHandle Handle,
+                             const MachineFunction *MF) {
     if (auto It = Vregs.find(std::make_pair(Handle, MF)); It != Vregs.end())
       return It->second;
     return nullptr;
   }
-  Register find(IRHandle Handle, const MachineFunction *MF) {
+  Register find(SPIRV::IRHandle Handle, const MachineFunction *MF) {
     const MachineInstr *MI = findMI(Handle, MF);
     return MI ? MI->getOperand(0).getReg() : Register();
   }
@@ -155,7 +157,7 @@ class SPIRVIRMapping {
   bool add(const Type *Ty, const MachineInstr *MI) {
     return add(SPIRV::make_descr_ptr(unifyPtrType(Ty)), MI);
   }
-  void add(const void *Key, const MachineInstr *MI) {
+  bool add(const void *Key, const MachineInstr *MI) {
     return add(SPIRV::make_descr_ptr(Key), MI);
   }
   bool add(const Type *PointeeTy, unsigned AddressSpace,
@@ -166,14 +168,25 @@ class SPIRVIRMapping {
   Register find(const Type *Ty, const MachineFunction *MF) {
     return find(SPIRV::make_descr_ptr(unifyPtrType(Ty)), MF);
   }
+  const MachineInstr *findMI(const Type *Ty, const MachineFunction *MF) {
+    return findMI(SPIRV::make_descr_ptr(unifyPtrType(Ty)), MF);
+  }
   Register find(const void *Key, const MachineFunction *MF) {
     return find(SPIRV::make_descr_ptr(Key), MF);
   }
+  const MachineInstr *findMI(const void *Key, const MachineFunction *MF) {
+    return findMI(SPIRV::make_descr_ptr(Key), MF);
+  }
   Register find(const Type *PointeeTy, unsigned AddressSpace,
                 const MachineFunction *MF) {
     return find(
         SPIRV::make_descr_pointee(unifyPtrType(PointeeTy), AddressSpace), MF);
   }
+  const MachineInstr *findMI(const Type *PointeeTy, unsigned AddressSpace,
+                             const MachineFunction *MF) {
+    return findMI(
+        SPIRV::make_descr_pointee(unifyPtrType(PointeeTy), AddressSpace), MF);
+  }
 };
 } // namespace llvm
 #endif // LLVM_LIB_TARGET_SPIRV_SPIRVIRMAPPING_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index ce9ce3ef3135c..aa82f7f7d936a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1213,16 +1213,17 @@ bool SPIRVInstructionSelector::selectMemOperation(Register ResVReg,
                                             true, GlobalValue::InternalLinkage,
                                             Constant::getNullValue(LLVMArrTy));
     Register VarReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
-    GR.add(GV, GR.CurMF, VarReg);
-    GR.addGlobalObject(GV, GR.CurMF, VarReg);
-
-    Result &=
+    auto MIBVar =
         BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpVariable))
             .addDef(VarReg)
             .addUse(GR.getSPIRVTypeID(VarTy))
             .addImm(SPIRV::StorageClass::UniformConstant)
-            .addUse(Const)
-            .constrainAllUses(TII, TRI, RBI);
+            .addUse(Const);
+    Result &= MIBVar.constrainAllUses(TII, TRI, RBI);
+
+    GR.add(GV, MIBVar);
+    GR.addGlobalObject(GV, GR.CurMF, VarReg);
+
     buildOpDecorate(VarReg, I, TII, SPIRV::Decoration::Constant, {});
     SPIRVType *SourceTy = GR.getOrCreateSPIRVPointerType(
         ValTy, I, TII, SPIRV::StorageClass::UniformConstant);
@@ -1555,7 +1556,7 @@ SPIRVInstructionSelector::buildConstGenericPtr(MachineInstr &I, Register SrcPtr,
   MachineInstrBuilder MIB = buildSpecConstantOp(
       I, Tmp, SrcPtr, GR.getSPIRVTypeID(GenericPtrTy),
       static_cast<uint32_t>(SPIRV::Opcode::PtrCastToGeneric));
-  GR.add(MIB.getInstr(), MF, Tmp);
+  GR.add(MIB.getInstr(), MIB);
   return MIB;
 }
 
@@ -2505,20 +2506,18 @@ SPIRVInstructionSelector::buildI32Constant(uint32_t Val, MachineInstr &I,
   bool Result = true;
   if (!NewReg.isValid()) {
     NewReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
-    GR.add(ConstInt, GR.CurMF, NewReg);
-    MachineInstr *MI;
     MachineBasicBlock &BB = *I.getParent();
-    if (Val == 0) {
-      MI = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
-               .addDef(NewReg)
-               .addUse(GR.getSPIRVTypeID(SpvI32Ty));
-    } else {
-      MI = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
-               .addDef(NewReg)
-               .addUse(GR.getSPIRVTypeID(SpvI32Ty))
-               .addImm(APInt(32, Val).getZExtValue());
-    }
+    MachineInstr *MI =
+        Val == 0
+            ? BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
+                  .addDef(NewReg)
+                  .addUse(GR.getSPIRVTypeID(SpvI32Ty))
+            : BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
+                  .addDef(NewReg)
+                  .addUse(GR.getSPIRVTypeID(SpvI32Ty))
+                  .addImm(APInt(32, Val).getZExtValue());
     Result &= constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
+    GR.add(ConstInt, MI);
   }
   return {NewReg, Result};
 }
@@ -2895,18 +2894,18 @@ bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
     }
     // Create a new register for the wrapper
     WrapReg = MRI->createVirtualRegister(GR.getRegClass(OpType));
-    GR.add(OpDefine, MF, WrapReg);
     CompositeArgs.push_back(WrapReg);
     // Decorate the wrapper register and generate a new instruction
     MRI->setType(WrapReg, LLT::pointer(0, 64));
     GR.assignSPIRVTypeToVReg(OpType, WrapReg, *MF);
-    MachineBasicBlock &BB = *I.getParent();
-    Result = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSpecConstantOp))
-                 .addDef(WrapReg)
-                 .addUse(GR.getSPIRVTypeID(OpType))
-                 .addImm(static_cast<uint32_t>(SPIRV::Opcode::Bitcast))
-                 .addUse(OpReg)
-                 .constrainAllUses(TII, TRI, RBI);
+    auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
+                       TII.get(SPIRV::OpSpecConstantOp))
+                   .addDef(WrapReg)
+                   .addUse(GR.getSPIRVTypeID(OpType))
+                   .addImm(static_cast<uint32_t>(SPIRV::Opcode::Bitcast))
+                   .addUse(OpReg);
+    GR.add(OpDefine, MIB);
+    Result = MIB.constrainAllUses(TII, TRI, RBI);
     if (!Result)
       break;
   }
@@ -3844,7 +3843,6 @@ bool SPIRVInstructionSelector::selectGlobalValue(
     Register NewReg = GR.find(ConstVal, GR.CurMF);
     if (!NewReg.isValid()) {
       Register NewReg = ResVReg;
-      GR.add(ConstVal, GR.CurMF, NewReg);
       const Function *GVFun =
           STI.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)
               ? dyn_cast<Function>(GV)
@@ -3872,15 +3870,18 @@ bool SPIRVInstructionSelector::selectGlobalValue(
                 .addDef(NewReg)
                 .addUse(ResTypeReg)
                 .addUse(FuncVReg);
+        GR.add(ConstVal, MIB2);
         // mapping the function pointer to the used Function
         GR.recordFunctionPointer(&MIB2.getInstr()->getOperand(2), GVFun);
         return MIB1.constrainAllUses(TII, TRI, RBI) &&
                MIB2.constrainAllUses(TII, TRI, RBI);
       }
-      return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
-          .addDef(NewReg)
-          .addUse(GR.getSPIRVTypeID(ResType))
-          .constrainAllUses(TII, TRI, RBI);
+      MachineInstrBuilder MIB3 =
+          BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
+              .addDef(NewReg)
+              .addUse(GR.getSPIRVTypeID(ResType));
+      GR.add(ConstVal, MIB3);
+      return MIB3.constrainAllUses(TII, TRI, RBI);
     }
     assert(NewReg != ResVReg);
     return BuildCOPY(ResVReg, NewReg, I);
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index edf215f0ce00f..da837c9ed85dd 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -48,8 +48,7 @@ void SPIRVPreLegalizer::getAnalysisUsage(AnalysisUsage &AU) const {
 static void
 addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR,
                     const SPIRVSubtarget &STI,
-                    DenseMap<MachineInstr *, Type *> &TargetExtConstTypes,
-                    SmallSet<Register, 4> &TrackedConstRegs) {
+                    DenseMap<MachineInstr *, Type *> &TargetExtConstTypes) {
   MachineRegisterInfo &MRI = MF.getRegInfo();
   DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
   SmallVector<MachineInstr *, 10> ToErase, ToEraseComposites;
@@ -66,7 +65,7 @@ addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR,
       if (auto *GV = dyn_cast<GlobalValue>(Const)) {
         Register Reg = GR->find(GV, &MF);
         if (!Reg.isValid()) {
-          GR->add(GV, &MF, SrcReg);
+          GR->add(GV, MRI.getVRegDef(SrcReg));
           GR->addGlobalObject(GV, &MF, SrcReg);
         } else
           RegsAlreadyAddedToDT[&MI] = Reg;
@@ -77,22 +76,24 @@ addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR,
             auto *BuildVec = MRI.getVRegDef(SrcReg);
             assert(BuildVec &&
                    BuildVec->getOpcode() == TargetOpcode::G_BUILD_VECTOR);
+            GR->add(Const, BuildVec);
             for (unsigned i = 0; i < ConstVec->getNumElements(); ++i) {
               // Ensure that OpConstantComposite reuses a constant when it's
               // already created and available in the same machine function.
               Constant *ElemConst = ConstVec->getElementAsConstant(i);
               Register ElemReg = GR->find(ElemConst, &MF);
               if (!ElemReg.isValid())
-                GR->add(ElemConst, &MF, BuildVec->getOperand(1 + i).getReg());
+                GR->add(ElemConst,
+                        MRI.getVRegDef(BuildVec->getOperand(1 + i).getReg()));
               else
                 BuildVec->getOperand(1 + i).setReg(ElemReg);
             }
           }
-          GR->add(Const, &MF, SrcReg);
-          TrackedConstRegs.insert(SrcReg);
           if (Const->getType()->isTargetExtTy()) {
             // remember association so that we can restore it when assign types
             MachineInstr *SrcMI = MRI.getVRegDef(SrcReg);
+            if (SrcMI)
+              GR->add(Const, SrcMI);
             if (SrcMI && (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT ||
                           SrcMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF))
               TargetExtConstTypes[SrcMI] = Const->getType();
@@ -595,7 +596,7 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
           // pointers/PtrCast-null-in-OpSpecConstantOp.ll).
           Register PrimaryReg = GR->find(OpCI, &MF);
           if (!PrimaryReg.isValid()) {
-            GR->add(OpCI, &MF, Reg);
+            GR->add(OpCI, &MI);
           } else if (PrimaryReg != Reg &&
                      MRI.getType(Reg) == MRI.getType(PrimaryReg)) {
             auto *RCReg = MRI.getRegClassOrNull(Reg);
@@ -730,7 +731,7 @@ insertInlineAsmProcess(MachineFunction &MF, SPIRVGlobalRegistry *GR,
       auto AsmTargetMIB =
           MIRBuilder.buildInstr(SPIRV::OpAsmTargetINTEL).addDef(AsmTargetReg);
       addStringImm(ST.getTargetTripleAsStr(), AsmTargetMIB);
-      GR->add(AsmTargetMIB.getInstr(), &MF, AsmTargetReg);
+      GR->add(AsmTargetMIB.getInstr(), AsmTargetMIB);
     }
 
     // create types
@@ -761,7 +762,7 @@ insertInlineAsmProcess(MachineFunction &MF, SPIRVGlobalRegistry *GR,
     addStringImm(cast<MDString>(I1->getOperand(2).getMetadata()->getOperand(0))
                      ->getString(),
                  AsmMIB);
-    GR->add(AsmMIB.getInstr(), &MF, AsmReg);
+    GR->add(AsmMIB.getInstr(), AsmMIB);
 
     // calls the inline assembly instruction
     unsigned ExtraInfo = I2->getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
@@ -1034,8 +1035,7 @@ bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
   // a registry of target extension constants
   DenseMap<MachineInstr *, Type *> TargetExtConstTypes;
   // to keep record of tracked constants
-  SmallSet<Register, 4> TrackedConstRegs;
-  addConstantsToTrack(MF, GR, ST, TargetExtConstTypes, TrackedConstRegs);
+  addConstantsToTrack(MF, GR, ST, TargetExtConstTypes);
   foldConstantsIntoIntrinsics(MF, MIB);
   insertBitcasts(MF, GR, MIB);
   generateAssignInstrs(MF, GR, MIB, TargetExtConstTypes);

>From 429551babc8637c4bcb58d07fae45ca3b4c6f568 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Fri, 14 Mar 2025 08:39:19 -0700
Subject: [PATCH 8/9] rework assign_type, type/const instruction selection

---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp       |   2 +-
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 113 ++++---
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h   |   6 +
 llvm/lib/Target/SPIRV/SPIRVIRMapping.h        | 155 ++++++---
 llvm/lib/Target/SPIRV/SPIRVInstrInfo.td       |   6 +-
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 297 +++++++++---------
 llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp  |  39 +--
 llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.h    |   2 -
 llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp  |  10 +-
 llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp   | 126 +++++---
 .../SPIRV/SPIRVPreLegalizerCombiner.cpp       |   7 +-
 llvm/lib/Target/SPIRV/SPIRVUtils.cpp          |  96 +++++-
 llvm/lib/Target/SPIRV/SPIRVUtils.h            |  12 +
 llvm/test/CodeGen/SPIRV/atomicrmw.ll          |   4 +-
 .../SPIRV/debug-info/debug-type-pointer.ll    |  44 +--
 llvm/test/CodeGen/SPIRV/freeze.ll             |  11 +-
 .../SPIRV/hlsl-intrinsics/dot4add_i8packed.ll |   2 +-
 .../SPIRV/hlsl-intrinsics/dot4add_u8packed.ll |   2 +-
 .../hlsl-resources/StorageImageDynIdx.ll      |   8 +-
 .../StorageImageNonUniformIdx.ll              |  10 +-
 .../llvm-intrinsics/smul.with.overflow.ll     |   6 +-
 .../llvm-intrinsics/uadd.with.overflow.ll     |   6 +-
 .../llvm-intrinsics/umul.with.overflow.ll     |   6 +-
 .../llvm-intrinsics/usub.with.overflow.ll     |   6 +-
 24 files changed, 577 insertions(+), 399 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index e6c0a526a9cec..4f5984d8823ab 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -535,7 +535,7 @@ static Register buildBuiltinVariableLoad(
 /// assign SPIRVType to both registers. If SpirvTy is provided, use it as
 /// SPIRVType in ASSIGN_TYPE, otherwise create it from \p Ty. Defined in
 /// SPIRVPreLegalizer.cpp.
-extern Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
+extern void insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
                                   SPIRVGlobalRegistry *GR,
                                   MachineIRBuilder &MIB,
                                   MachineRegisterInfo &MRI);
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 62e4d50b1926a..07138c625a1af 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -250,24 +250,32 @@ Register SPIRVGlobalRegistry::getOrCreateConstFP(APFloat Val, MachineInstr &I,
                                                  SPIRVType *SpvType,
                                                  const SPIRVInstrInfo &TII,
                                                  bool ZeroAsNull) {
-  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
   LLVMContext &Ctx = CurMF->getFunction().getContext();
   auto *const CF = ConstantFP::get(Ctx, Val);
-  Register Res = find(CF, CurMF);
-  if (Res.isValid())
-    return Res;
+  const MachineInstr *MI = findMI(CF, CurMF);
+  if (MI && (MI->getOpcode() == SPIRV::OpConstantNull ||
+             MI->getOpcode() == SPIRV::OpConstantF))
+    return MI->getOperand(0).getReg();
+  return createConstFP(CF, I, SpvType, TII, ZeroAsNull);
+}
 
+Register SPIRVGlobalRegistry::createConstFP(const ConstantFP *CF,
+                                            MachineInstr &I, SPIRVType *SpvType,
+                                            const SPIRVInstrInfo &TII,
+                                            bool ZeroAsNull) {
+  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
   LLT LLTy = LLT::scalar(BitWidth);
-  Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
+  Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
   CurMF->getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
   assignFloatTypeToVReg(BitWidth, Res, I, TII);
 
-  MachineIRBuilder MIRBuilder(I);
+  MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
+  MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
   SPIRVType *NewType =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
         MachineInstrBuilder MIB;
         // In OpenCL OpConstantNull - Scalar floating point: +0.0 (all bits 0)
-        if (Val.isPosZero() && ZeroAsNull) {
+        if (CF->getValue().isPosZero() && ZeroAsNull) {
           MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
                     .addDef(Res)
                     .addUse(getSPIRVTypeID(SpvType));
@@ -294,24 +302,35 @@ Register SPIRVGlobalRegistry::getOrCreateConstInt(uint64_t Val, MachineInstr &I,
                                                   const SPIRVInstrInfo &TII,
                                                   bool ZeroAsNull) {
   const IntegerType *Ty = cast<IntegerType>(getTypeForSPIRVType(SpvType));
-  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
   auto *const CI = ConstantInt::get(const_cast<IntegerType *>(Ty), Val);
-  Register Res = find(CI, CurMF);
-  if (Res.isValid())
-    return Res;
+  const MachineInstr *MI = findMI(CI, CurMF);
+  if (MI && (MI->getOpcode() == SPIRV::OpConstantNull ||
+             MI->getOpcode() == SPIRV::OpConstantI))
+    return MI->getOperand(0).getReg();
+  return createConstInt(CI, I, SpvType, TII, ZeroAsNull);
+}
+
+Register SPIRVGlobalRegistry::createConstInt(const ConstantInt *CI,
+                                             MachineInstr &I,
+                                             SPIRVType *SpvType,
+                                             const SPIRVInstrInfo &TII,
+                                             bool ZeroAsNull) {
+  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
   LLT LLTy = LLT::scalar(BitWidth);
-  Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
+  Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
   CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
   assignIntTypeToVReg(BitWidth, Res, I, TII);
-  MachineIRBuilder MIRBuilder(I);
+
+  MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
+  MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
   SPIRVType *NewType =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
         MachineInstrBuilder MIB;
-        if (Val || !ZeroAsNull) {
+        if (!CI->isZero() || !ZeroAsNull) {
           MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
                     .addDef(Res)
                     .addUse(getSPIRVTypeID(SpvType));
-          addNumImm(APInt(BitWidth, Val), MIB);
+          addNumImm(APInt(BitWidth, CI->getZExtValue()), MIB);
         } else {
           MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
                     .addDef(Res)
@@ -441,7 +460,8 @@ Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull(
   CurMF->getRegInfo().setRegClass(Res, getRegClass(SpvType));
   assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
 
-  MachineIRBuilder MIRBuilder(I);
+  MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
+  MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
   const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
         MachineInstrBuilder MIB;
@@ -751,11 +771,7 @@ static std::string buildSpirvTypeName(const SPIRVType *Type,
     MachineRegisterInfo *MRI = MIRBuilder.getMRI();
     Register ElementTypeReg = Type->getOperand(1).getReg();
     auto *ElementType = MRI->getUniqueVRegDef(ElementTypeReg);
-    const SPIRVType *TypeInst = MRI->getVRegDef(Type->getOperand(2).getReg());
-    assert(TypeInst->getOpcode() != SPIRV::OpConstantI);
-    MachineInstr *ImmInst = MRI->getVRegDef(TypeInst->getOperand(1).getReg());
-    assert(ImmInst->getOpcode() == TargetOpcode::G_CONSTANT);
-    uint32_t ArraySize = ImmInst->getOperand(1).getCImm()->getZExtValue();
+    uint32_t ArraySize = getArrayComponentCount(MRI, Type);
     return (buildSpirvTypeName(ElementType, MIRBuilder) + Twine("[") +
             Twine(ArraySize) + Twine("]"))
         .str();
@@ -1274,9 +1290,9 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeImage(
     uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
     SPIRV::ImageFormat::ImageFormat ImageFormat,
     SPIRV::AccessQualifier::AccessQualifier AccessQual) {
-  auto Key = SPIRV::make_descr_image(SPIRVToLLVMType.lookup(SampledType), Dim,
-                                     Depth, Arrayed, Multisampled, Sampled,
-                                     ImageFormat, AccessQual);
+  auto Key = SPIRV::irhandle_image(SPIRVToLLVMType.lookup(SampledType), Dim,
+                                   Depth, Arrayed, Multisampled, Sampled,
+                                   ImageFormat, AccessQual);
   if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
     return MI;
   const MachineInstr *NewMI =
@@ -1301,7 +1317,7 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeImage(
 
 SPIRVType *
 SPIRVGlobalRegistry::getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder) {
-  auto Key = SPIRV::make_descr_sampler();
+  auto Key = SPIRV::irhandle_sampler();
   const MachineFunction *MF = &MIRBuilder.getMF();
   if (const MachineInstr *MI = findMI(Key, MF))
     return MI;
@@ -1317,7 +1333,7 @@ SPIRVGlobalRegistry::getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder) {
 SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypePipe(
     MachineIRBuilder &MIRBuilder,
     SPIRV::AccessQualifier::AccessQualifier AccessQual) {
-  auto Key = SPIRV::make_descr_pipe(AccessQual);
+  auto Key = SPIRV::irhandle_pipe(AccessQual);
   if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
     return MI;
   const MachineInstr *NewMI =
@@ -1332,7 +1348,7 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypePipe(
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeDeviceEvent(
     MachineIRBuilder &MIRBuilder) {
-  auto Key = SPIRV::make_descr_event();
+  auto Key = SPIRV::irhandle_event();
   if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
     return MI;
   const MachineInstr *NewMI =
@@ -1346,7 +1362,7 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeDeviceEvent(
 
 SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeSampledImage(
     SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
-  auto Key = SPIRV::make_descr_sampled_image(
+  auto Key = SPIRV::irhandle_sampled_image(
       SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
           ImageType->getOperand(1).getReg())),
       ImageType);
@@ -1465,10 +1481,12 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(unsigned BitWidth,
                                                      Type *Ty) {
   if (const MachineInstr *MI = findMI(Ty, CurMF))
     return MI;
-  MachineIRBuilder MIRBuilder(I);
+  MachineBasicBlock &DepMBB = I.getMF()->front();
+  MachineIRBuilder MIRBuilder(DepMBB, DepMBB.getFirstNonPHI());
   const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-        return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRVOPcode))
+        return BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
+                       MIRBuilder.getDL(), TII.get(SPIRVOPcode))
             .addDef(createTypeVReg(CurMF->getRegInfo()))
             .addImm(BitWidth)
             .addImm(0);
@@ -1522,11 +1540,12 @@ SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineInstr &I,
   Type *Ty = IntegerType::get(CurMF->getFunction().getContext(), 1);
   if (const MachineInstr *MI = findMI(Ty, CurMF))
     return MI;
-  MachineIRBuilder MIRBuilder(I);
+  MachineBasicBlock &DepMBB = I.getMF()->front();
+  MachineIRBuilder MIRBuilder(DepMBB, DepMBB.getFirstNonPHI());
   const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-        return BuildMI(*I.getParent(), I, I.getDebugLoc(),
-                       TII.get(SPIRV::OpTypeBool))
+        return BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
+                       MIRBuilder.getDL(), TII.get(SPIRV::OpTypeBool))
             .addDef(createTypeVReg(CurMF->getRegInfo()));
       });
   add(Ty, NewMI);
@@ -1549,11 +1568,12 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
       const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
   if (const MachineInstr *MI = findMI(Ty, CurMF))
     return MI;
-  MachineIRBuilder MIRBuilder(I);
+  MachineInstr *DepMI = const_cast<MachineInstr *>(BaseType);
+  MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
   const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-        return BuildMI(*I.getParent(), I, I.getDebugLoc(),
-                       TII.get(SPIRV::OpTypeVector))
+        return BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
+                       MIRBuilder.getDL(), TII.get(SPIRV::OpTypeVector))
             .addDef(createTypeVReg(CurMF->getRegInfo()))
             .addUse(getSPIRVTypeID(BaseType))
             .addImm(NumElements);
@@ -1571,11 +1591,12 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVArrayType(
     return MI;
   SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, I, TII);
   Register Len = getOrCreateConstInt(NumElements, I, SpvTypeInt32, TII);
-  MachineIRBuilder MIRBuilder(I);
+  MachineBasicBlock &DepMBB = I.getMF()->front();
+  MachineIRBuilder MIRBuilder(DepMBB, getInsertPtValidEnd(&DepMBB));
   const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-        return BuildMI(*I.getParent(), I, I.getDebugLoc(),
-                       TII.get(SPIRV::OpTypeArray))
+        return BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
+                       MIRBuilder.getDL(), TII.get(SPIRV::OpTypeArray))
             .addDef(createTypeVReg(CurMF->getRegInfo()))
             .addUse(getSPIRVTypeID(BaseType))
             .addUse(Len);
@@ -1609,7 +1630,8 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
 SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
     SPIRVType *BaseType, MachineInstr &I, const SPIRVInstrInfo &,
     SPIRV::StorageClass::StorageClass SC) {
-  MachineIRBuilder MIRBuilder(I);
+  MachineInstr *DepMI = const_cast<MachineInstr *>(BaseType);
+  MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
   return getOrCreateSPIRVPointerType(BaseType, MIRBuilder, SC);
 }
 
@@ -1627,13 +1649,14 @@ Register SPIRVGlobalRegistry::getOrCreateUndef(MachineInstr &I,
   CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
   assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
 
-  MachineIRBuilder MIRBuilder(I);
+  MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
+  MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
   const MachineInstr *NewMI =
       createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
-        auto MIB =
-            BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
-                .addDef(Res)
-                .addUse(getSPIRVTypeID(SpvType));
+        auto MIB = BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
+                           MIRBuilder.getDL(), TII.get(SPIRV::OpUndef))
+                       .addDef(Res)
+                       .addUse(getSPIRVTypeID(SpvType));
         const auto &ST = CurMF->getSubtarget();
         constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
                                          *ST.getRegisterInfo(),
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index 3c6c11fae92b3..385e424092d4a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -473,9 +473,15 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
   Register getOrCreateConstInt(uint64_t Val, MachineInstr &I,
                                SPIRVType *SpvType, const SPIRVInstrInfo &TII,
                                bool ZeroAsNull = true);
+  Register createConstInt(const ConstantInt *CI, MachineInstr &I,
+                          SPIRVType *SpvType, const SPIRVInstrInfo &TII,
+                          bool ZeroAsNull);
   Register getOrCreateConstFP(APFloat Val, MachineInstr &I, SPIRVType *SpvType,
                               const SPIRVInstrInfo &TII,
                               bool ZeroAsNull = true);
+  Register createConstFP(const ConstantFP *CF, MachineInstr &I,
+                         SPIRVType *SpvType, const SPIRVInstrInfo &TII,
+                         bool ZeroAsNull);
   Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder,
                            SPIRVType *SpvType = nullptr);
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVIRMapping.h b/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
index 8f1a345565630..bec2a989483e8 100644
--- a/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
+++ b/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
@@ -18,7 +18,7 @@
 #include "MCTargetDesc/SPIRVMCTargetDesc.h"
 #include "SPIRVUtils.h"
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/Hashing.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 
@@ -27,7 +27,39 @@
 namespace llvm {
 namespace SPIRV {
 
+inline size_t to_hash(const MachineInstr *MI,
+                      std::unordered_set<const MachineInstr *> &Visited) {
+  if (!MI || !Visited.insert(MI).second)
+    return 0;
+  const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
+  SmallVector<size_t, 16> Codes{MI->getOpcode()};
+  size_t H;
+  for (unsigned I = MI->getNumDefs(); I < MI->getNumOperands(); ++I) {
+    const MachineOperand &MO = MI->getOperand(I);
+    H = MO.isReg() ? to_hash(getDef(MO, &MRI), Visited)
+                   : size_t(llvm::hash_value(MO));
+    Codes.push_back(H);
+  }
+  return llvm::hash_combine(Codes.begin(), Codes.end());
+}
+
+inline size_t to_hash(const MachineInstr *MI) {
+  std::unordered_set<const MachineInstr *> Visited;
+  return to_hash(MI, Visited);
+}
+
+using MIHandle = std::pair<const MachineInstr *, size_t>;
+
+inline MIHandle getMIKey(const MachineInstr *MI) {
+  return std::make_pair(MI, SPIRV::to_hash(MI));
+}
+
 using IRHandle = std::tuple<const void *, unsigned, unsigned>;
+using IRHandleMF = std::pair<IRHandle, const MachineFunction *>;
+
+inline IRHandleMF getIRHandleMF(IRHandle Handle, const MachineFunction *MF) {
+  return std::make_pair(Handle, MF);
+}
 
 enum SpecialTypeKind {
   STK_Empty = 0,
@@ -37,7 +69,9 @@ enum SpecialTypeKind {
   STK_Pipe,
   STK_DeviceEvent,
   STK_ElementPointer,
-  STK_Pointer,
+  STK_Type,
+  STK_Value,
+  STK_MachineInstr,
   STK_Last = -1
 };
 
@@ -66,18 +100,18 @@ union ImageAttrs {
   }
 };
 
-inline IRHandle make_descr_image(const Type *SampledTy, unsigned Dim,
-                                 unsigned Depth, unsigned Arrayed, unsigned MS,
-                                 unsigned Sampled, unsigned ImageFormat,
-                                 unsigned AQ = 0) {
+inline IRHandle irhandle_image(const Type *SampledTy, unsigned Dim,
+                               unsigned Depth, unsigned Arrayed, unsigned MS,
+                               unsigned Sampled, unsigned ImageFormat,
+                               unsigned AQ = 0) {
   return std::make_tuple(
       SampledTy,
       ImageAttrs(Dim, Depth, Arrayed, MS, Sampled, ImageFormat, AQ).Val,
       SpecialTypeKind::STK_Image);
 }
 
-inline IRHandle make_descr_sampled_image(const Type *SampledTy,
-                                         const MachineInstr *ImageTy) {
+inline IRHandle irhandle_sampled_image(const Type *SampledTy,
+                                       const MachineInstr *ImageTy) {
   assert(ImageTy->getOpcode() == SPIRV::OpTypeImage);
   unsigned AC = AccessQualifier::AccessQualifier::None;
   if (ImageTy->getNumOperands() > 8)
@@ -92,61 +126,90 @@ inline IRHandle make_descr_sampled_image(const Type *SampledTy,
       SpecialTypeKind::STK_SampledImage);
 }
 
-inline IRHandle make_descr_sampler() {
+inline IRHandle irhandle_sampler() {
   return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_Sampler);
 }
 
-inline IRHandle make_descr_pipe(uint8_t AQ) {
+inline IRHandle irhandle_pipe(uint8_t AQ) {
   return std::make_tuple(nullptr, AQ, SpecialTypeKind::STK_Pipe);
 }
 
-inline IRHandle make_descr_event() {
+inline IRHandle irhandle_event() {
   return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_DeviceEvent);
 }
 
-inline IRHandle make_descr_pointee(const Type *ElementType,
-                                   unsigned AddressSpace) {
-  return std::make_tuple(ElementType, AddressSpace,
+inline IRHandle irhandle_pointee(const Type *ElementType,
+                                 unsigned AddressSpace) {
+  return std::make_tuple(unifyPtrType(ElementType), AddressSpace,
                          SpecialTypeKind::STK_ElementPointer);
 }
 
-inline IRHandle make_descr_ptr(const void *Ptr, unsigned Arg = 0U) {
-  return std::make_tuple(Ptr, Arg, SpecialTypeKind::STK_Pointer);
+inline IRHandle irhandle_ptr(const void *Ptr, unsigned Arg,
+                             enum SpecialTypeKind STK) {
+  return std::make_tuple(Ptr, Arg, STK);
+}
+
+inline IRHandle handle(const Type *Ty) {
+  const Type *WrpTy = unifyPtrType(Ty);
+  return irhandle_ptr(WrpTy, Ty->getTypeID(), STK_Type);
 }
+
+inline IRHandle handle(const Value *V) {
+  return irhandle_ptr(V, V->getValueID(), STK_Value);
+}
+
+inline IRHandle handle(const MachineInstr *KeyMI) {
+  return irhandle_ptr(KeyMI, SPIRV::to_hash(KeyMI), STK_MachineInstr);
+}
+
 } // namespace SPIRV
 
 // Bi-directional mappings between LLVM entities and (v-reg, machine function)
 // pairs support management of unique SPIR-V definitions per machine function
 // per an LLVM/GlobalISel entity (e.g., Type, Constant, Machine Instruction).
 class SPIRVIRMapping {
-  DenseMap<std::pair<SPIRV::IRHandle, const MachineFunction *>,
-           const MachineInstr *>
-      Vregs;
-  DenseMap<const MachineInstr *, SPIRV::IRHandle> Defs;
+  DenseMap<SPIRV::IRHandleMF, SPIRV::MIHandle> Vregs;
+  DenseMap<SPIRV::MIHandle, SPIRV::IRHandle> Defs;
 
 public:
   bool add(SPIRV::IRHandle Handle, const MachineInstr *MI) {
+    if (std::get<1>(Handle) == 17 && std::get<2>(Handle) == 8) {
+      const Value *Ptr = (const Value *)std::get<0>(Handle);
+      if (const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(Ptr)) {
+        if (CI->getZExtValue() == 8 || CI->getZExtValue() == 5) {
+          [[maybe_unused]] uint64_t v = CI->getZExtValue();
+        }
+      }
+    }
+    auto MIKey = SPIRV::getMIKey(MI);
     auto [It, Inserted] =
-        Vregs.try_emplace(std::make_pair(Handle, MI->getMF()), MI);
+        Vregs.try_emplace(std::make_pair(Handle, MI->getMF()), MIKey);
     if (Inserted) {
-      auto [_, IsConsistent] = Defs.insert_or_assign(MI, Handle);
+      [[maybe_unused]] auto [_, IsConsistent] =
+          Defs.insert_or_assign(MIKey, Handle);
       assert(IsConsistent);
     }
     return Inserted;
   }
   bool erase(const MachineInstr *MI) {
     bool Res = false;
-    if (auto It = Defs.find(MI); It != Defs.end()) {
-      Res = Vregs.erase(std::make_pair(It->second, MI->getMF()));
+    if (auto It = Defs.find(SPIRV::getMIKey(MI)); It != Defs.end()) {
+      Res = Vregs.erase(SPIRV::getIRHandleMF(It->second, MI->getMF()));
       Defs.erase(It);
     }
     return Res;
   }
   const MachineInstr *findMI(SPIRV::IRHandle Handle,
                              const MachineFunction *MF) {
-    if (auto It = Vregs.find(std::make_pair(Handle, MF)); It != Vregs.end())
-      return It->second;
-    return nullptr;
+    auto It = Vregs.find(SPIRV::getIRHandleMF(Handle, MF));
+    if (It == Vregs.end())
+      return nullptr;
+    auto [MI, Hash] = It->second;
+    if (SPIRV::to_hash(MI) != Hash) {
+      erase(MI);
+      return nullptr;
+    }
+    return MI;
   }
   Register find(SPIRV::IRHandle Handle, const MachineFunction *MF) {
     const MachineInstr *MI = findMI(Handle, MF);
@@ -154,38 +217,28 @@ class SPIRVIRMapping {
   }
 
   // helpers
-  bool add(const Type *Ty, const MachineInstr *MI) {
-    return add(SPIRV::make_descr_ptr(unifyPtrType(Ty)), MI);
-  }
-  bool add(const void *Key, const MachineInstr *MI) {
-    return add(SPIRV::make_descr_ptr(Key), MI);
-  }
   bool add(const Type *PointeeTy, unsigned AddressSpace,
            const MachineInstr *MI) {
-    return add(SPIRV::make_descr_pointee(unifyPtrType(PointeeTy), AddressSpace),
-               MI);
-  }
-  Register find(const Type *Ty, const MachineFunction *MF) {
-    return find(SPIRV::make_descr_ptr(unifyPtrType(Ty)), MF);
-  }
-  const MachineInstr *findMI(const Type *Ty, const MachineFunction *MF) {
-    return findMI(SPIRV::make_descr_ptr(unifyPtrType(Ty)), MF);
-  }
-  Register find(const void *Key, const MachineFunction *MF) {
-    return find(SPIRV::make_descr_ptr(Key), MF);
-  }
-  const MachineInstr *findMI(const void *Key, const MachineFunction *MF) {
-    return findMI(SPIRV::make_descr_ptr(Key), MF);
+    return add(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MI);
   }
   Register find(const Type *PointeeTy, unsigned AddressSpace,
                 const MachineFunction *MF) {
-    return find(
-        SPIRV::make_descr_pointee(unifyPtrType(PointeeTy), AddressSpace), MF);
+    return find(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MF);
   }
   const MachineInstr *findMI(const Type *PointeeTy, unsigned AddressSpace,
                              const MachineFunction *MF) {
-    return findMI(
-        SPIRV::make_descr_pointee(unifyPtrType(PointeeTy), AddressSpace), MF);
+    return findMI(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MF);
+  }
+
+  template <typename T> bool add(const T *Obj, const MachineInstr *MI) {
+    return add(SPIRV::handle(Obj), MI);
+  }
+  template <typename T> Register find(const T *Obj, const MachineFunction *MF) {
+    return find(SPIRV::handle(Obj), MF);
+  }
+  template <typename T>
+  const MachineInstr *findMI(const T *Obj, const MachineFunction *MF) {
+    return findMI(SPIRV::handle(Obj), MF);
   }
 };
 } // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
index a8f862271dbab..4b9bddd661f63 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
+++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
@@ -15,6 +15,7 @@ include "SPIRVSymbolicOperands.td"
 
 // Codegen only metadata instructions
 let isCodeGenOnly=1 in {
+  def TYPEREF: Pseudo<(outs), (ins ID:$src_id, TYPE:$src_ty)>;
   def ASSIGN_TYPE: Pseudo<(outs ID:$dst_id), (ins ID:$src_id, TYPE:$src_ty)>;
   def DECL_TYPE: Pseudo<(outs ID:$dst_id), (ins ID:$src_id, TYPE:$src_ty)>;
   def GET_ID: Pseudo<(outs iID:$dst_id), (ins iID:$src)>;
@@ -28,8 +29,10 @@ let isCodeGenOnly=1 in {
 def SPVTypeBin : SDTypeProfile<1, 2, []>;
 
 def assigntype : SDNode<"SPIRVISD::AssignType", SPVTypeBin>;
+def typeref : SDNode<"SPIRVISD::TypeRef", SPVTypeBin>;
 
 def : GINodeEquiv<ASSIGN_TYPE, assigntype>;
+def : GINodeEquiv<TYPEREF, typeref>;
 
 class BinOp<string name, bits<16> opCode, list<dag> pattern=[]>
                 : Op<opCode, (outs ID:$dst), (ins TYPE:$src_ty, ID:$src, ID:$src2),
@@ -472,11 +475,8 @@ def OpConvertBF16ToFINTEL : UnOp<"OpConvertBF16ToFINTEL", 6117>;
 
 // 3.42.12 Composite Instructions
 
-//def OpVectorExtractDynamic: Op<77, (outs ID:$res), (ins TYPE:$type, vID:$vec, ID:$idx),
-//                  "$res = OpVectorExtractDynamic $type $vec $idx", [(set ID:$res, (assigntype (extractelt vID:$vec, ID:$idx), TYPE:$type))]>;
 def OpVectorExtractDynamic: Op<77, (outs ID:$res), (ins TYPE:$type, vID:$vec, ID:$idx),
                   "$res = OpVectorExtractDynamic $type $vec $idx">;
-
 def OpVectorInsertDynamic: Op<78, (outs ID:$res), (ins TYPE:$ty, ID:$vec, ID:$comp, ID:$idx),
                   "$res = OpVectorInsertDynamic $ty $vec $comp $idx">;
 def OpVectorShuffle: Op<79, (outs ID:$res), (ins TYPE:$ty, ID:$v1, ID:$v2, variable_ops),
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index aa82f7f7d936a..8f1ac07dd9450 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -393,27 +393,84 @@ void SPIRVInstructionSelector::resetVRegsType(MachineFunction &MF) {
   }
   for (const auto &MBB : MF) {
     for (const auto &MI : MBB) {
-      if (MI.getOpcode() != SPIRV::ASSIGN_TYPE)
-        continue;
-      Register DstReg = MI.getOperand(0).getReg();
-      LLT DstType = MRI.getType(DstReg);
-      Register SrcReg = MI.getOperand(1).getReg();
-      LLT SrcType = MRI.getType(SrcReg);
-      if (DstType != SrcType)
-        MRI.setType(DstReg, MRI.getType(SrcReg));
-
-      const TargetRegisterClass *DstRC = MRI.getRegClassOrNull(DstReg);
-      const TargetRegisterClass *SrcRC = MRI.getRegClassOrNull(SrcReg);
-      if (DstRC != SrcRC && SrcRC)
-        MRI.setRegClass(DstReg, SrcRC);
+      if (MI.getOpcode() == SPIRV::ASSIGN_TYPE) {
+        Register DstReg = MI.getOperand(0).getReg();
+        LLT DstType = MRI.getType(DstReg);
+        Register SrcReg = MI.getOperand(1).getReg();
+        LLT SrcType = MRI.getType(SrcReg);
+        if (DstType != SrcType)
+          MRI.setType(DstReg, MRI.getType(SrcReg));
+
+        const TargetRegisterClass *DstRC = MRI.getRegClassOrNull(DstReg);
+        const TargetRegisterClass *SrcRC = MRI.getRegClassOrNull(SrcReg);
+        if (DstRC != SrcRC && SrcRC)
+          MRI.setRegClass(DstReg, SrcRC);
+      } else if (MI.getOpcode() == SPIRV::TYPEREF) {
+        Register DstReg = MI.getOperand(0).getReg();
+        LLT DstType = MRI.getType(DstReg);
+        Register SrcReg = MI.getOperand(1).getReg();
+        LLT SrcType = MRI.getType(SrcReg);
+        if (DstType != SrcType)
+          MRI.setType(DstReg, MRI.getType(SrcReg));
+      }
     }
   }
 }
 
-static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI);
+// Return true if the type represents a constant register
+static bool isConstReg(MachineRegisterInfo *MRI, MachineInstr *OpDef,
+                       SmallPtrSet<SPIRVType *, 4> &Visited) {
+  OpDef = passCopy(OpDef, MRI);
+
+  if (Visited.contains(OpDef))
+    return true;
+  Visited.insert(OpDef);
+
+  unsigned Opcode = OpDef->getOpcode();
+  switch (Opcode) {
+  case TargetOpcode::G_CONSTANT:
+  case TargetOpcode::G_FCONSTANT:
+    return true;
+  case TargetOpcode::G_INTRINSIC:
+  case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
+  case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
+    return cast<GIntrinsic>(*OpDef).getIntrinsicID() ==
+           Intrinsic::spv_const_composite;
+  case TargetOpcode::G_BUILD_VECTOR:
+  case TargetOpcode::G_SPLAT_VECTOR: {
+    for (unsigned i = OpDef->getNumExplicitDefs(); i < OpDef->getNumOperands();
+         i++) {
+      MachineInstr *OpNestedDef =
+          OpDef->getOperand(i).isReg()
+              ? MRI->getVRegDef(OpDef->getOperand(i).getReg())
+              : nullptr;
+      if (OpNestedDef && !isConstReg(MRI, OpNestedDef, Visited))
+        return false;
+    }
+    return true;
+  case SPIRV::OpConstantTrue:
+  case SPIRV::OpConstantFalse:
+  case SPIRV::OpConstantI:
+  case SPIRV::OpConstantF:
+  case SPIRV::OpConstantComposite:
+  case SPIRV::OpConstantCompositeContinuedINTEL:
+  case SPIRV::OpConstantSampler:
+  case SPIRV::OpConstantNull:
+  case SPIRV::OpUndef:
+  case SPIRV::OpConstantFunctionPointerINTEL:
+    return true;
+  }
+  }
+  return false;
+}
 
-// Defined in SPIRVLegalizerInfo.cpp.
-extern bool isTypeFoldingSupported(unsigned Opcode);
+// Return true if the virtual register represents a constant
+static bool isConstReg(MachineRegisterInfo *MRI, Register OpReg) {
+  SmallPtrSet<SPIRVType *, 4> Visited;
+  if (MachineInstr *OpDef = MRI->getVRegDef(OpReg))
+    return isConstReg(MRI, OpDef, Visited);
+  return false;
+}
 
 bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI) {
   for (const auto &MO : MI.all_defs()) {
@@ -466,6 +523,27 @@ bool SPIRVInstructionSelector::select(MachineInstr &I) {
       GR.invalidateMachineInstr(&I);
       I.removeFromParent();
       return true;
+    } else if (Opcode == SPIRV::TYPEREF) {
+      Register SrcReg = I.getOperand(0).getReg();
+      auto *Def = MRI->getVRegDef(SrcReg);
+      if (isTypeFoldingSupported(Def->getOpcode())) {
+        bool Res = selectImpl(I, *CoverageInfo);
+        LLVM_DEBUG({
+          if (!Res && Def->getOpcode() != TargetOpcode::G_CONSTANT) {
+            dbgs() << "Unexpected pattern in ASSIGN_TYPE.\nInstruction: ";
+            I.print(dbgs());
+          }
+        });
+        assert(Res || Def->getOpcode() == TargetOpcode::G_CONSTANT);
+        if (Res) {
+          if (!isTriviallyDead(*Def, *MRI) && isDead(*Def, *MRI))
+            DeadMIs.insert(Def);
+          return Res;
+        }
+      }
+      GR.invalidateMachineInstr(&I);
+      I.removeFromParent();
+      return true;
     } else if (I.getNumDefs() == 1) {
       // Make all vregs 64 bits (for SPIR-V IDs).
       MRI->setType(I.getOperand(0).getReg(), LLT::scalar(64));
@@ -766,7 +844,7 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
     assert(((*II).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
             (*II).getOpcode() == TargetOpcode::COPY ||
             (*II).getOpcode() == SPIRV::OpVariable) &&
-           isImm(I.getOperand(2), MRI));
+           getImm(I.getOperand(2), MRI));
     // It may be the initialization of a global variable.
     bool IsGVInit = false;
     for (MachineRegisterInfo::use_instr_iterator
@@ -2003,27 +2081,30 @@ bool SPIRVInstructionSelector::selectDot4AddPackedExpansion(
   auto ExtractOp =
       Signed ? SPIRV::OpBitFieldSExtract : SPIRV::OpBitFieldUExtract;
 
+  bool ZeroAsNull = STI.isOpenCLEnv();
   // Extract the i8 element, multiply and add it to the accumulator
   for (unsigned i = 0; i < 4; i++) {
     // A[i]
     Register AElt = MRI->createVirtualRegister(&SPIRV::IDRegClass);
-    Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
-                  .addDef(AElt)
-                  .addUse(GR.getSPIRVTypeID(ResType))
-                  .addUse(I.getOperand(2).getReg())
-                  .addUse(GR.getOrCreateConstInt(i * 8, I, EltType, TII))
-                  .addUse(GR.getOrCreateConstInt(8, I, EltType, TII))
-                  .constrainAllUses(TII, TRI, RBI);
+    Result &=
+        BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
+            .addDef(AElt)
+            .addUse(GR.getSPIRVTypeID(ResType))
+            .addUse(I.getOperand(2).getReg())
+            .addUse(GR.getOrCreateConstInt(i * 8, I, EltType, TII, ZeroAsNull))
+            .addUse(GR.getOrCreateConstInt(8, I, EltType, TII, ZeroAsNull))
+            .constrainAllUses(TII, TRI, RBI);
 
     // B[i]
     Register BElt = MRI->createVirtualRegister(&SPIRV::IDRegClass);
-    Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
-                  .addDef(BElt)
-                  .addUse(GR.getSPIRVTypeID(ResType))
-                  .addUse(I.getOperand(3).getReg())
-                  .addUse(GR.getOrCreateConstInt(i * 8, I, EltType, TII))
-                  .addUse(GR.getOrCreateConstInt(8, I, EltType, TII))
-                  .constrainAllUses(TII, TRI, RBI);
+    Result &=
+        BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
+            .addDef(BElt)
+            .addUse(GR.getSPIRVTypeID(ResType))
+            .addUse(I.getOperand(3).getReg())
+            .addUse(GR.getOrCreateConstInt(i * 8, I, EltType, TII, ZeroAsNull))
+            .addUse(GR.getOrCreateConstInt(8, I, EltType, TII, ZeroAsNull))
+            .constrainAllUses(TII, TRI, RBI);
 
     // A[i] * B[i]
     Register Mul = MRI->createVirtualRegister(&SPIRV::IDRegClass);
@@ -2036,13 +2117,14 @@ bool SPIRVInstructionSelector::selectDot4AddPackedExpansion(
 
     // Discard 24 highest-bits so that stored i32 register is i8 equivalent
     Register MaskMul = MRI->createVirtualRegister(&SPIRV::IDRegClass);
-    Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
-                  .addDef(MaskMul)
-                  .addUse(GR.getSPIRVTypeID(ResType))
-                  .addUse(Mul)
-                  .addUse(GR.getOrCreateConstInt(0, I, EltType, TII))
-                  .addUse(GR.getOrCreateConstInt(8, I, EltType, TII))
-                  .constrainAllUses(TII, TRI, RBI);
+    Result &=
+        BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
+            .addDef(MaskMul)
+            .addUse(GR.getSPIRVTypeID(ResType))
+            .addUse(Mul)
+            .addUse(GR.getOrCreateConstInt(0, I, EltType, TII, ZeroAsNull))
+            .addUse(GR.getOrCreateConstInt(8, I, EltType, TII, ZeroAsNull))
+            .constrainAllUses(TII, TRI, RBI);
 
     // Acc = Acc + A[i] * B[i]
     Register Sum =
@@ -2139,7 +2221,7 @@ bool SPIRVInstructionSelector::selectWaveOpInst(Register ResVReg,
                  .addDef(ResVReg)
                  .addUse(GR.getSPIRVTypeID(ResType))
                  .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I,
-                                                IntTy, TII));
+                                                IntTy, TII, STI.isOpenCLEnv()));
 
   for (unsigned J = 2; J < I.getNumOperands(); J++) {
     BMI.addUse(I.getOperand(J).getReg());
@@ -2158,15 +2240,15 @@ bool SPIRVInstructionSelector::selectWaveActiveCountBits(
                                  SPIRV::OpGroupNonUniformBallot);
 
   MachineBasicBlock &BB = *I.getParent();
-  Result &=
-      BuildMI(BB, I, I.getDebugLoc(),
-              TII.get(SPIRV::OpGroupNonUniformBallotBitCount))
-          .addDef(ResVReg)
-          .addUse(GR.getSPIRVTypeID(ResType))
-          .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I, IntTy, TII))
-          .addImm(SPIRV::GroupOperation::Reduce)
-          .addUse(BallotReg)
-          .constrainAllUses(TII, TRI, RBI);
+  Result &= BuildMI(BB, I, I.getDebugLoc(),
+                    TII.get(SPIRV::OpGroupNonUniformBallotBitCount))
+                .addDef(ResVReg)
+                .addUse(GR.getSPIRVTypeID(ResType))
+                .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I, IntTy,
+                                               TII, STI.isOpenCLEnv()))
+                .addImm(SPIRV::GroupOperation::Reduce)
+                .addUse(BallotReg)
+                .constrainAllUses(TII, TRI, RBI);
 
   return Result;
 }
@@ -2193,7 +2275,8 @@ bool SPIRVInstructionSelector::selectWaveReduceMax(Register ResVReg,
   return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
       .addDef(ResVReg)
       .addUse(GR.getSPIRVTypeID(ResType))
-      .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I, IntTy, TII))
+      .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I, IntTy, TII,
+                                     STI.isOpenCLEnv()))
       .addImm(SPIRV::GroupOperation::Reduce)
       .addUse(I.getOperand(2).getReg())
       .constrainAllUses(TII, TRI, RBI);
@@ -2219,7 +2302,8 @@ bool SPIRVInstructionSelector::selectWaveReduceSum(Register ResVReg,
   return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
       .addDef(ResVReg)
       .addUse(GR.getSPIRVTypeID(ResType))
-      .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I, IntTy, TII))
+      .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I, IntTy, TII,
+                                     STI.isOpenCLEnv()))
       .addImm(SPIRV::GroupOperation::Reduce)
       .addUse(I.getOperand(2).getReg());
 }
@@ -2247,6 +2331,8 @@ bool SPIRVInstructionSelector::selectFreeze(Register ResVReg,
     return false;
   Register OpReg = I.getOperand(1).getReg();
   if (MachineInstr *Def = MRI->getVRegDef(OpReg)) {
+    if (Def->getOpcode() == TargetOpcode::COPY)
+      Def = MRI->getVRegDef(Def->getOperand(1).getReg());
     Register Reg;
     switch (Def->getOpcode()) {
     case SPIRV::ASSIGN_TYPE:
@@ -2275,82 +2361,6 @@ bool SPIRVInstructionSelector::selectFreeze(Register ResVReg,
   return false;
 }
 
-static unsigned getArrayComponentCount(MachineRegisterInfo *MRI,
-                                       const SPIRVType *ResType) {
-  Register OpReg = ResType->getOperand(2).getReg();
-  SPIRVType *OpDef = MRI->getVRegDef(OpReg);
-  if (!OpDef)
-    return 0;
-  if (OpDef->getOpcode() == SPIRV::ASSIGN_TYPE &&
-      OpDef->getOperand(1).isReg()) {
-    if (SPIRVType *RefDef = MRI->getVRegDef(OpDef->getOperand(1).getReg()))
-      OpDef = RefDef;
-  }
-  unsigned N = OpDef->getOpcode() == TargetOpcode::G_CONSTANT
-                   ? OpDef->getOperand(1).getCImm()->getValue().getZExtValue()
-                   : 0;
-  return N;
-}
-
-// Return true if the type represents a constant register
-static bool isConstReg(MachineRegisterInfo *MRI, SPIRVType *OpDef,
-                       SmallPtrSet<SPIRVType *, 4> &Visited) {
-  if (OpDef->getOpcode() == SPIRV::ASSIGN_TYPE &&
-      OpDef->getOperand(1).isReg()) {
-    if (SPIRVType *RefDef = MRI->getVRegDef(OpDef->getOperand(1).getReg()))
-      OpDef = RefDef;
-  }
-
-  if (Visited.contains(OpDef))
-    return true;
-  Visited.insert(OpDef);
-
-  unsigned Opcode = OpDef->getOpcode();
-  switch (Opcode) {
-  case TargetOpcode::G_CONSTANT:
-  case TargetOpcode::G_FCONSTANT:
-    return true;
-  case TargetOpcode::G_INTRINSIC:
-  case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
-  case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
-    return cast<GIntrinsic>(*OpDef).getIntrinsicID() ==
-           Intrinsic::spv_const_composite;
-  case TargetOpcode::G_BUILD_VECTOR:
-  case TargetOpcode::G_SPLAT_VECTOR: {
-    for (unsigned i = OpDef->getNumExplicitDefs(); i < OpDef->getNumOperands();
-         i++) {
-      SPIRVType *OpNestedDef =
-          OpDef->getOperand(i).isReg()
-              ? MRI->getVRegDef(OpDef->getOperand(i).getReg())
-              : nullptr;
-      if (OpNestedDef && !isConstReg(MRI, OpNestedDef, Visited))
-        return false;
-    }
-    return true;
-  case SPIRV::OpConstantTrue:
-  case SPIRV::OpConstantFalse:
-  case SPIRV::OpConstantI:
-  case SPIRV::OpConstantF:
-  case SPIRV::OpConstantComposite:
-  case SPIRV::OpConstantCompositeContinuedINTEL:
-  case SPIRV::OpConstantSampler:
-  case SPIRV::OpConstantNull:
-  case SPIRV::OpUndef:
-  case SPIRV::OpConstantFunctionPointerINTEL:
-    return true;
-  }
-  }
-  return false;
-}
-
-// Return true if the virtual register represents a constant
-static bool isConstReg(MachineRegisterInfo *MRI, Register OpReg) {
-  SmallPtrSet<SPIRVType *, 4> Visited;
-  if (SPIRVType *OpDef = MRI->getVRegDef(OpReg))
-    return isConstReg(MRI, OpDef, Visited);
-  return false;
-}
-
 bool SPIRVInstructionSelector::selectBuildVector(Register ResVReg,
                                                  const SPIRVType *ResType,
                                                  MachineInstr &I) const {
@@ -2740,7 +2750,15 @@ bool SPIRVInstructionSelector::selectConst(Register ResVReg,
         .constrainAllUses(TII, TRI, RBI);
   if (TyOpcode == SPIRV::OpTypeInt) {
     assert(Imm.getBitWidth() <= 64 && "Unsupported integer width!");
-    Register Reg = GR.getOrCreateConstInt(Imm.getZExtValue(), I, ResType, TII);
+    const ConstantInt *CI =
+        ConstantInt::get(const_cast<IntegerType *>(cast<IntegerType>(
+                             GR.getTypeForSPIRVType(ResType))),
+                         Imm.getZExtValue());
+    const MachineInstr *ConstMI = GR.findMI(CI, GR.CurMF);
+    Register Reg =
+        (ConstMI && ConstMI != &I)
+            ? ConstMI->getOperand(0).getReg()
+            : GR.createConstInt(CI, I, ResType, TII, STI.isOpenCLEnv());
     return Reg == ResVReg ? true : BuildCOPY(ResVReg, Reg, I);
   }
   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
@@ -2761,25 +2779,6 @@ bool SPIRVInstructionSelector::selectOpUndef(Register ResVReg,
       .constrainAllUses(TII, TRI, RBI);
 }
 
-static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI) {
-  assert(MO.isReg());
-  const SPIRVType *TypeInst = MRI->getVRegDef(MO.getReg());
-  if (TypeInst->getOpcode() == SPIRV::ASSIGN_TYPE) {
-    assert(TypeInst->getOperand(1).isReg());
-    MachineInstr *ImmInst = MRI->getVRegDef(TypeInst->getOperand(1).getReg());
-    return ImmInst->getOpcode() == TargetOpcode::G_CONSTANT;
-  }
-  return TypeInst->getOpcode() == SPIRV::OpConstantI;
-}
-
-static int64_t foldImm(const MachineOperand &MO, MachineRegisterInfo *MRI) {
-  const SPIRVType *TypeInst = MRI->getVRegDef(MO.getReg());
-  if (TypeInst->getOpcode() == SPIRV::OpConstantI)
-    return TypeInst->getOperand(2).getImm();
-  MachineInstr *ImmInst = MRI->getVRegDef(TypeInst->getOperand(1).getReg());
-  assert(ImmInst->getOpcode() == TargetOpcode::G_CONSTANT);
-  return ImmInst->getOperand(1).getCImm()->getZExtValue();
-}
 
 bool SPIRVInstructionSelector::selectInsertVal(Register ResVReg,
                                                const SPIRVType *ResType,
@@ -2813,7 +2812,7 @@ bool SPIRVInstructionSelector::selectExtractVal(Register ResVReg,
 bool SPIRVInstructionSelector::selectInsertElt(Register ResVReg,
                                                const SPIRVType *ResType,
                                                MachineInstr &I) const {
-  if (isImm(I.getOperand(4), MRI))
+  if (getImm(I.getOperand(4), MRI))
     return selectInsertVal(ResVReg, ResType, I);
   MachineBasicBlock &BB = *I.getParent();
   return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpVectorInsertDynamic))
@@ -2828,7 +2827,7 @@ bool SPIRVInstructionSelector::selectInsertElt(Register ResVReg,
 bool SPIRVInstructionSelector::selectExtractElt(Register ResVReg,
                                                 const SPIRVType *ResType,
                                                 MachineInstr &I) const {
-  if (isImm(I.getOperand(3), MRI))
+  if (getImm(I.getOperand(3), MRI))
     return selectExtractVal(ResVReg, ResType, I);
   MachineBasicBlock &BB = *I.getParent();
   return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpVectorExtractDynamic))
@@ -2875,7 +2874,7 @@ bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
   unsigned Lim = I.getNumExplicitOperands();
   for (unsigned i = I.getNumExplicitDefs() + 1; i < Lim; ++i) {
     Register OpReg = I.getOperand(i).getReg();
-    SPIRVType *OpDefine = MRI->getVRegDef(OpReg);
+    MachineInstr *OpDefine = MRI->getVRegDef(OpReg);
     SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpReg);
     SmallPtrSet<SPIRVType *, 4> Visited;
     if (!OpDefine || !OpType || isConstReg(MRI, OpDefine, Visited) ||
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index daa8ea52ffe03..520ea169fd638 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -24,43 +24,6 @@ using namespace llvm;
 using namespace llvm::LegalizeActions;
 using namespace llvm::LegalityPredicates;
 
-// clang-format off
-static const std::set<unsigned> TypeFoldingSupportingOpcs = {
-    TargetOpcode::G_ADD,
-    TargetOpcode::G_FADD,
-    TargetOpcode::G_STRICT_FADD,
-    TargetOpcode::G_SUB,
-    TargetOpcode::G_FSUB,
-    TargetOpcode::G_STRICT_FSUB,
-    TargetOpcode::G_MUL,
-    TargetOpcode::G_FMUL,
-    TargetOpcode::G_STRICT_FMUL,
-    TargetOpcode::G_SDIV,
-    TargetOpcode::G_UDIV,
-    TargetOpcode::G_FDIV,
-    TargetOpcode::G_STRICT_FDIV,
-    TargetOpcode::G_SREM,
-    TargetOpcode::G_UREM,
-    TargetOpcode::G_FREM,
-    TargetOpcode::G_STRICT_FREM,
-    TargetOpcode::G_FNEG,
-    TargetOpcode::G_CONSTANT,
-    TargetOpcode::G_FCONSTANT,
-    TargetOpcode::G_AND,
-    TargetOpcode::G_OR,
-    TargetOpcode::G_XOR,
-    TargetOpcode::G_SHL,
-    TargetOpcode::G_ASHR,
-    TargetOpcode::G_LSHR,
-    TargetOpcode::G_SELECT,
-    TargetOpcode::G_EXTRACT_VECTOR_ELT,
-};
-// clang-format on
-
-bool isTypeFoldingSupported(unsigned Opcode) {
-  return TypeFoldingSupportingOpcs.count(Opcode) > 0;
-}
-
 LegalityPredicate typeOfExtendedScalars(unsigned TypeIdx, bool IsExtendedInts) {
   return [IsExtendedInts, TypeIdx](const LegalityQuery &Query) {
     const LLT Ty = Query.Types[TypeIdx];
@@ -181,7 +144,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
         return IsExtendedInts && Ty.isValid();
       };
 
-  for (auto Opc : TypeFoldingSupportingOpcs)
+  for (auto Opc : getTypeFoldingSupportedOpcodes())
     getActionDefinitionsBuilder(Opc).custom();
 
   getActionDefinitionsBuilder(G_GLOBAL_VALUE).alwaysLegal();
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.h b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.h
index f18b15b7f1696..6335f211e1986 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.h
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.h
@@ -16,8 +16,6 @@
 #include "SPIRVGlobalRegistry.h"
 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
 
-bool isTypeFoldingSupported(unsigned Opcode);
-
 namespace llvm {
 
 class LLVMContext;
diff --git a/llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp
index e7b942e42b0a2..4c20688e9e983 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp
@@ -41,15 +41,11 @@ class SPIRVPostLegalizer : public MachineFunctionPass {
 };
 } // namespace
 
-// Defined in SPIRVLegalizerInfo.cpp.
-extern bool isTypeFoldingSupported(unsigned Opcode);
-
 namespace llvm {
 //  Defined in SPIRVPreLegalizer.cpp.
-extern Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
-                                  SPIRVGlobalRegistry *GR,
-                                  MachineIRBuilder &MIB,
-                                  MachineRegisterInfo &MRI);
+extern void insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
+                              SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
+                              MachineRegisterInfo &MRI);
 extern void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
                          MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR);
 } // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index da837c9ed85dd..0ece31ee88abe 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -98,7 +98,8 @@ addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR,
                           SrcMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF))
               TargetExtConstTypes[SrcMI] = Const->getType();
             if (Const->isNullValue()) {
-              MachineIRBuilder MIB(MF);
+              MachineBasicBlock &DepMBB = MF.front();
+              MachineIRBuilder MIB(DepMBB, DepMBB.getFirstNonPHI());
               SPIRVType *ExtType = GR->getOrCreateSPIRVType(
                   Const->getType(), MIB, SPIRV::AccessQualifier::ReadWrite,
                   true);
@@ -128,13 +129,17 @@ addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR,
     if (!MRI.getRegClassOrNull(Reg) && RC)
       MRI.setRegClass(Reg, RC);
     MRI.replaceRegWith(MI->getOperand(0).getReg(), Reg);
+    GR->invalidateMachineInstr(MI);
     MI->eraseFromParent();
   }
-  for (MachineInstr *MI : ToEraseComposites)
+  for (MachineInstr *MI : ToEraseComposites) {
+    GR->invalidateMachineInstr(MI);
     MI->eraseFromParent();
+  }
 }
 
 static void foldConstantsIntoIntrinsics(MachineFunction &MF,
+                                        SPIRVGlobalRegistry *GR,
                                         MachineIRBuilder MIB) {
   SmallVector<MachineInstr *, 64> ToErase;
   for (MachineBasicBlock &MBB : MF) {
@@ -149,8 +154,10 @@ static void foldConstantsIntoIntrinsics(MachineFunction &MF,
       }
       ToErase.push_back(&MI);
     }
-    for (MachineInstr *MI : ToErase)
+    for (MachineInstr *MI : ToErase) {
+      GR->invalidateMachineInstr(MI);
       MI->eraseFromParent();
+    }
     ToErase.clear();
   }
 }
@@ -219,8 +226,10 @@ static void selectOpBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR,
       ToErase.push_back(&MI);
     }
   }
-  for (MachineInstr *MI : ToErase)
+  for (MachineInstr *MI : ToErase) {
+    GR->invalidateMachineInstr(MI);
     MI->eraseFromParent();
+  }
 }
 
 static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR,
@@ -264,8 +273,10 @@ static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR,
       }
     }
   }
-  for (MachineInstr *MI : ToErase)
+  for (MachineInstr *MI : ToErase) {
+    GR->invalidateMachineInstr(MI);
     MI->eraseFromParent();
+  }
 }
 
 // Translating GV, IRTranslator sometimes generates following IR:
@@ -384,7 +395,7 @@ static void widenScalarLLTNextPow2(Register Reg, MachineRegisterInfo &MRI) {
   if (NewSz != Sz)
     MRI.setType(Reg, LLT::scalar(NewSz));
 }
-
+/*
 static std::pair<Register, unsigned>
 createNewIdReg(SPIRVType *SpvType, Register SrcReg, MachineRegisterInfo &MRI,
                const SPIRVGlobalRegistry &GR) {
@@ -406,7 +417,7 @@ createNewIdReg(SPIRVType *SpvType, Register SrcReg, MachineRegisterInfo &MRI,
     GetIdOp = SPIRV::GET_vID;
   return {Reg, GetIdOp};
 }
-
+*/
 static void setInsertPtAfterDef(MachineIRBuilder &MIB, MachineInstr *Def) {
   MachineBasicBlock &MBB = *Def->getParent();
   MachineBasicBlock::iterator DefIt =
@@ -418,21 +429,31 @@ static void setInsertPtAfterDef(MachineIRBuilder &MIB, MachineInstr *Def) {
   MIB.setInsertPt(MBB, DefIt);
 }
 
-// Insert ASSIGN_TYPE instuction between Reg and its definition, set NewReg as
-// a dst of the definition, assign SPIRVType to both registers. If SpvType is
-// provided, use it as SPIRVType in ASSIGN_TYPE, otherwise create it from Ty.
-// It's used also in SPIRVBuiltins.cpp.
-// TODO: maybe move to SPIRVUtils.
 namespace llvm {
-Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpvType,
-                           SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
-                           MachineRegisterInfo &MRI) {
+void insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpvType,
+                       SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
+                       MachineRegisterInfo &MRI) {
   assert((Ty || SpvType) && "Either LLVM or SPIRV type is expected.");
   MachineInstr *Def = MRI.getVRegDef(Reg);
   setInsertPtAfterDef(MIB, Def);
-  SpvType = SpvType ? SpvType
-                    : GR->getOrCreateSPIRVType(
-                          Ty, MIB, SPIRV::AccessQualifier::ReadWrite, true);
+  if (!SpvType)
+    SpvType = GR->getOrCreateSPIRVType(Ty, MIB,
+                                       SPIRV::AccessQualifier::ReadWrite, true);
+
+  if (!isTypeFoldingSupported(Def->getOpcode())) {
+    // No need to generate SPIRV::ASSIGN_TYPE pseudo-instruction
+    if (!GR->getSPIRVTypeForVReg(Reg, &MRI.getMF())) {
+      if (!MRI.getRegClassOrNull(Reg))
+        MRI.setRegClass(Reg, GR->getRegClass(SpvType));
+      if (!MRI.getType(Reg).isValid())
+        MRI.setType(Reg, GR->getRegType(SpvType));
+      GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
+    }
+    return;
+  }
+
+  // Tablegen definition assumes SPIRV::ASSIGN_TYPE pseudo-instruction is
+  // present after each auto-folded instruction to take a type reference from.
   Register NewReg = MRI.createGenericVirtualRegister(MRI.getType(Reg));
   if (auto *RC = MRI.getRegClassOrNull(Reg)) {
     MRI.setRegClass(NewReg, RC);
@@ -460,12 +481,27 @@ Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpvType,
       break;
     }
   }
-  return NewReg;
 }
 
 void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
                   MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR) {
   MIB.setInsertPt(*MI.getParent(), MI.getIterator());
+  for (auto &Op : MI.operands()) {
+    if (!Op.isReg() || Op.isDef())
+      continue;
+    Register OpReg = Op.getReg();
+    SPIRVType *SpvType = GR->getSPIRVTypeForVReg(OpReg);
+    assert(SpvType);
+    if (!MRI.getRegClassOrNull(OpReg))
+      MRI.setRegClass(OpReg, GR->getRegClass(SpvType));
+    if (!MRI.getType(OpReg).isValid())
+      MRI.setType(OpReg, GR->getRegType(SpvType));
+  }
+}
+
+/*void processInstr2(MachineInstr &MI, MachineIRBuilder &MIB,
+                  MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR) {
+  MIB.setInsertPt(*MI.getParent(), MI.getIterator());
   for (auto &Op : MI.operands()) {
     if (!Op.isReg() || Op.isDef())
       continue;
@@ -478,7 +514,7 @@ void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
       MRI.setRegClass(OpReg, RC);
     Op.setReg(IdOpInfo.first);
   }
-}
+}*/
 } // namespace llvm
 
 static void
@@ -528,7 +564,8 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
         assert(Def && "Expecting an instruction that defines the register");
         // G_GLOBAL_VALUE already has type info.
         if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
-            Def->getOpcode() != SPIRV::ASSIGN_TYPE)
+            Def->getOpcode() != SPIRV::ASSIGN_TYPE &&
+            Def->getOpcode() != SPIRV::TYPEREF)
           insertAssignInstr(Reg, nullptr, AssignedPtrType, GR, MIB,
                             MF.getRegInfo());
         ToErase.push_back(&MI);
@@ -539,7 +576,8 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
         assert(Def && "Expecting an instruction that defines the register");
         // G_GLOBAL_VALUE already has type info.
         if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
-            Def->getOpcode() != SPIRV::ASSIGN_TYPE)
+            Def->getOpcode() != SPIRV::ASSIGN_TYPE &&
+            Def->getOpcode() != SPIRV::TYPEREF)
           insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
         ToErase.push_back(&MI);
       } else if (MIOp == TargetOpcode::FAKE_USE && MI.getNumOperands() > 0) {
@@ -576,7 +614,8 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
           if (isSpvIntrinsic(UseMI, Intrinsic::spv_assign_type) ||
               isSpvIntrinsic(UseMI, Intrinsic::spv_assign_name))
             continue;
-          if (UseMI.getOpcode() == SPIRV::ASSIGN_TYPE)
+          if (UseMI.getOpcode() == SPIRV::ASSIGN_TYPE ||
+              UseMI.getOpcode() == SPIRV::TYPEREF)
             NeedAssignType = false;
         }
         Type *Ty = nullptr;
@@ -620,11 +659,18 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
           } else if (ElemMI->getOpcode() == TargetOpcode::G_FCONSTANT) {
             ElemTy = ElemMI->getOperand(1).getFPImm()->getType();
           } else {
-            // There may be a case when we already know Reg's type.
-            MachineInstr *NextMI = MI.getNextNode();
-            if (!NextMI || NextMI->getOpcode() != SPIRV::ASSIGN_TYPE ||
-                NextMI->getOperand(1).getReg() != Reg)
-              llvm_unreachable("Unexpected opcode");
+            if (const SPIRVType *ElemSpvType =
+                    GR->getSPIRVTypeForVReg(MI.getOperand(1).getReg(), &MF))
+              ElemTy = const_cast<Type *>(GR->getTypeForSPIRVType(ElemSpvType));
+            if (!ElemTy) {
+              // There may be a case when we already know Reg's type.
+              MachineInstr *NextMI = MI.getNextNode();
+              if (!NextMI ||
+                  (NextMI->getOpcode() != SPIRV::ASSIGN_TYPE &&
+                   NextMI->getOpcode() != SPIRV::TYPEREF) ||
+                  NextMI->getOperand(1).getReg() != Reg)
+                llvm_unreachable("Unexpected opcode");
+            }
           }
           if (ElemTy)
             Ty = VectorType::get(
@@ -649,6 +695,7 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
     auto It = RegsAlreadyAddedToDT.find(MI);
     if (It != RegsAlreadyAddedToDT.end())
       MRI.replaceRegWith(MI->getOperand(0).getReg(), It->second);
+    GR->invalidateMachineInstr(MI);
     MI->eraseFromParent();
   }
 
@@ -671,9 +718,6 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
   }
 }
 
-// Defined in SPIRVLegalizerInfo.cpp.
-extern bool isTypeFoldingSupported(unsigned Opcode);
-
 static void processInstrsWithTypeFolding(MachineFunction &MF,
                                          SPIRVGlobalRegistry *GR,
                                          MachineIRBuilder MIB) {
@@ -788,8 +832,10 @@ insertInlineAsmProcess(MachineFunction &MF, SPIRVGlobalRegistry *GR,
     for (unsigned IntrIdx = 3; IntrIdx < I1->getNumOperands(); ++IntrIdx)
       AsmCall.addUse(I1->getOperand(IntrIdx).getReg());
   }
-  for (MachineInstr *MI : ToProcess)
+  for (MachineInstr *MI : ToProcess) {
+    GR->invalidateMachineInstr(MI);
     MI->eraseFromParent();
+  }
 }
 
 static void insertInlineAsm(MachineFunction &MF, SPIRVGlobalRegistry *GR,
@@ -835,8 +881,10 @@ static void insertSpirvDecorations(MachineFunction &MF, SPIRVGlobalRegistry *GR,
       ToErase.push_back(&MI);
     }
   }
-  for (MachineInstr *MI : ToErase)
+  for (MachineInstr *MI : ToErase) {
+    GR->invalidateMachineInstr(MI);
     MI->eraseFromParent();
+  }
 }
 
 // LLVM allows the switches to use registers as cases, while SPIR-V required
@@ -875,7 +923,8 @@ static void processSwitchesConstants(MachineFunction &MF,
 
 // Some instructions are used during CodeGen but should never be emitted.
 // Cleaning up those.
-static void cleanupHelperInstructions(MachineFunction &MF) {
+static void cleanupHelperInstructions(MachineFunction &MF,
+                                      SPIRVGlobalRegistry *GR) {
   SmallVector<MachineInstr *, 8> ToEraseMI;
   for (MachineBasicBlock &MBB : MF) {
     for (MachineInstr &MI : MBB) {
@@ -885,8 +934,10 @@ static void cleanupHelperInstructions(MachineFunction &MF) {
     }
   }
 
-  for (MachineInstr *MI : ToEraseMI)
+  for (MachineInstr *MI : ToEraseMI) {
+    GR->invalidateMachineInstr(MI);
     MI->eraseFromParent();
+  }
 }
 
 // Find all usages of G_BLOCK_ADDR in our intrinsics and replace those
@@ -988,6 +1039,7 @@ static void processBlockAddr(MachineFunction &MF, SPIRVGlobalRegistry *GR,
           ConstantExpr::getIntToPtr(Replacement, BA->getType()));
       BA->destroyConstant();
     }
+    GR->invalidateMachineInstr(BlockAddrI);
     BlockAddrI->eraseFromParent();
   }
 }
@@ -1036,13 +1088,13 @@ bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
   DenseMap<MachineInstr *, Type *> TargetExtConstTypes;
   // to keep record of tracked constants
   addConstantsToTrack(MF, GR, ST, TargetExtConstTypes);
-  foldConstantsIntoIntrinsics(MF, MIB);
+  foldConstantsIntoIntrinsics(MF, GR, MIB);
   insertBitcasts(MF, GR, MIB);
   generateAssignInstrs(MF, GR, MIB, TargetExtConstTypes);
 
   processSwitchesConstants(MF, GR, MIB);
   processBlockAddr(MF, GR, MIB);
-  cleanupHelperInstructions(MF);
+  cleanupHelperInstructions(MF, GR);
 
   processInstrsWithTypeFolding(MF, GR, MIB);
   removeImplicitFallthroughs(MF, MIB);
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizerCombiner.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizerCombiner.cpp
index 269524b2410c2..71f08aedd7777 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizerCombiner.cpp
@@ -96,16 +96,21 @@ void applySPIRVDistance(MachineInstr &MI, MachineRegisterInfo &MRI,
       .addUse(SubOperand1)                     // Operand X
       .addUse(SubOperand2);                    // Operand Y
 
+  SPIRVGlobalRegistry *GR =
+      MI.getMF()->getSubtarget<SPIRVSubtarget>().getSPIRVGlobalRegistry();
   auto RemoveAllUses = [&](Register Reg) {
     SmallVector<MachineInstr *, 4> UsesToErase;
     for (auto &UseMI : MRI.use_instructions(Reg))
       UsesToErase.push_back(&UseMI);
 
     // calling eraseFromParent to early invalidates the iterator.
-    for (auto *MIToErase : UsesToErase)
+    for (auto *MIToErase : UsesToErase) {
+      GR->invalidateMachineInstr(MIToErase);
       MIToErase->eraseFromParent();
+    }
   };
   RemoveAllUses(SubDestReg);   // remove all uses of FSUB Result
+  GR->invalidateMachineInstr(SubInstr);
   SubInstr->eraseFromParent(); // remove FSUB instruction
 }
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index 8380cd579004d..6e6125c7bd66d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -186,7 +186,8 @@ MachineBasicBlock::iterator getOpVariableMBBIt(MachineInstr &I) {
     if (Opcode == SPIRV::OpFunction || Opcode == SPIRV::OpFunctionParameter) {
       IsHeader = true;
     } else if (IsHeader &&
-               !(Opcode == SPIRV::ASSIGN_TYPE || Opcode == SPIRV::OpLabel)) {
+               !(Opcode == SPIRV::ASSIGN_TYPE || Opcode == SPIRV::TYPEREF ||
+                 Opcode == SPIRV::OpLabel)) {
       ++It;
       break;
     }
@@ -303,20 +304,7 @@ SPIRV::Scope::Scope getMemScope(LLVMContext &Ctx, SyncScope::ID Id) {
     return SPIRV::Scope::Device;
   return SPIRV::Scope::CrossDevice;
 }
-/*
-MachineInstr *getDefInstrMaybeConstant(Register &ConstReg,
-                                       const MachineRegisterInfo *MRI) {
-  MachineInstr *MI = MRI->getVRegDef(ConstReg);
-  //if (MI->getOpcode() == SPIRV::G_TRUNC || MI->getOpcode() == SPIRV::G_ZEXT)
-  //  return getDefInstrMaybeConstant(ConstReg = MI->getOperand(1).getReg(), MRI);
-  if (MI->getOpcode() == SPIRV::ASSIGN_TYPE)
-    return getDefInstrMaybeConstant(ConstReg = MI->getOperand(1).getReg(), MRI);
-  if (auto *GI = dyn_cast<GIntrinsic>(MI))
-    if (GI->is(Intrinsic::spv_track_constant))
-      return MRI->getVRegDef(ConstReg = MI->getOperand(2).getReg());
-  return MI;
-}
-*/
+
 MachineInstr *getDefInstrMaybeConstant(Register &ConstReg,
                                        const MachineRegisterInfo *MRI) {
   MachineInstr *MI = MRI->getVRegDef(ConstReg);
@@ -860,4 +848,82 @@ void createContinuedInstructions(MachineIRBuilder &MIRBuilder, unsigned Opcode,
   }
 }
 
+const std::set<unsigned> &getTypeFoldingSupportedOpcodes() {
+  // clang-format off
+  static const std::set<unsigned> TypeFoldingSupportingOpcs = {
+    TargetOpcode::G_ADD,
+    TargetOpcode::G_FADD,
+    TargetOpcode::G_STRICT_FADD,
+    TargetOpcode::G_SUB,
+    TargetOpcode::G_FSUB,
+    TargetOpcode::G_STRICT_FSUB,
+    TargetOpcode::G_MUL,
+    TargetOpcode::G_FMUL,
+    TargetOpcode::G_STRICT_FMUL,
+    TargetOpcode::G_SDIV,
+    TargetOpcode::G_UDIV,
+    TargetOpcode::G_FDIV,
+    TargetOpcode::G_STRICT_FDIV,
+    TargetOpcode::G_SREM,
+    TargetOpcode::G_UREM,
+    TargetOpcode::G_FREM,
+    TargetOpcode::G_STRICT_FREM,
+    TargetOpcode::G_FNEG,
+    TargetOpcode::G_CONSTANT,
+    TargetOpcode::G_FCONSTANT,
+    TargetOpcode::G_AND,
+    TargetOpcode::G_OR,
+    TargetOpcode::G_XOR,
+    TargetOpcode::G_SHL,
+    TargetOpcode::G_ASHR,
+    TargetOpcode::G_LSHR,
+    TargetOpcode::G_SELECT,
+    TargetOpcode::G_EXTRACT_VECTOR_ELT,
+  };
+  // clang-format on
+  return TypeFoldingSupportingOpcs;
+}
+
+bool isTypeFoldingSupported(unsigned Opcode) {
+  return getTypeFoldingSupportedOpcodes().count(Opcode) > 0;
+}
+
+// Traversing [g]MIR accounting for pseudo-instructions.
+MachineInstr *passCopy(MachineInstr *Def, const MachineRegisterInfo *MRI) {
+  return (Def->getOpcode() == SPIRV::ASSIGN_TYPE ||
+          Def->getOpcode() == TargetOpcode::COPY)
+             ? MRI->getVRegDef(Def->getOperand(1).getReg())
+             : Def;
+}
+
+MachineInstr *getDef(const MachineOperand &MO, const MachineRegisterInfo *MRI) {
+  if (MachineInstr *Def = MRI->getVRegDef(MO.getReg()))
+    return passCopy(Def, MRI);
+  return nullptr;
+}
+
+MachineInstr *getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI) {
+  if (MachineInstr *Def = getDef(MO, MRI)) {
+    if (Def->getOpcode() == TargetOpcode::G_CONSTANT ||
+        Def->getOpcode() == SPIRV::OpConstantI)
+      return Def;
+  }
+  return nullptr;
+}
+
+int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI) {
+  if (MachineInstr *Def = getImm(MO, MRI)) {
+    if (Def->getOpcode() == SPIRV::OpConstantI)
+      return Def->getOperand(2).getImm();
+    if (Def->getOpcode() == TargetOpcode::G_CONSTANT)
+      return Def->getOperand(1).getCImm()->getZExtValue();
+  }
+  llvm_unreachable("Unexpected integer constant pattern");
+}
+
+unsigned getArrayComponentCount(const MachineRegisterInfo *MRI,
+                                const MachineInstr *ResType) {
+  return foldImm(ResType->getOperand(2), MRI);
+}
+
 } // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h
index 180d3a29d170f..a0b8ba18fc7ba 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.h
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h
@@ -459,5 +459,17 @@ void createContinuedInstructions(MachineIRBuilder &MIRBuilder, unsigned Opcode,
                                  ArrayRef<Register> Args,
                                  Register ReturnRegister, Register TypeID);
 
+// Instruction selection directed by type folding.
+const std::set<unsigned> &getTypeFoldingSupportedOpcodes();
+bool isTypeFoldingSupported(unsigned Opcode);
+
+// Traversing [g]MIR accounting for pseudo-instructions.
+MachineInstr *passCopy(MachineInstr *Def, const MachineRegisterInfo *MRI);
+MachineInstr *getDef(const MachineOperand &MO, const MachineRegisterInfo *MRI);
+MachineInstr *getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI);
+int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI);
+unsigned getArrayComponentCount(const MachineRegisterInfo *MRI,
+                                const MachineInstr *ResType);
+
 } // namespace llvm
 #endif // LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H
diff --git a/llvm/test/CodeGen/SPIRV/atomicrmw.ll b/llvm/test/CodeGen/SPIRV/atomicrmw.ll
index 07576056117cb..a6cfe56cd06c3 100644
--- a/llvm/test/CodeGen/SPIRV/atomicrmw.ll
+++ b/llvm/test/CodeGen/SPIRV/atomicrmw.ll
@@ -4,8 +4,8 @@
 ; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
-; CHECK:     %[[#Int:]] = OpTypeInt 32 0
-; CHECK-DAG: %[[#Scope_CrossDevice:]] = OpConstant %[[#Int]] 0{{$}}
+; CHECK-DAG: %[[#Int:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#Scope_CrossDevice:]] = OpConstantNull %[[#Int]]
 ; CHECK-DAG: %[[#MemSem_Acquire:]] = OpConstant %[[#Int]] 2
 ; CHECK-DAG: %[[#MemSem_Release:]] = OpConstant %[[#Int]] 4{{$}}
 ; CHECK-DAG: %[[#MemSem_AcquireRelease:]] = OpConstant %[[#Int]] 8
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll
index 93ea49afc6589..2b29b4fca5671 100644
--- a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll
@@ -6,23 +6,23 @@
 
 ; CHECK-MIR-DAG:   [[i32type:%[0-9]+\:type]] = OpTypeInt 32, 0
 ; CHECK-MIR-DAG:   [[void_type:%[0-9]+\:type\(s64\)]] = OpTypeVoid
-; CHECK-MIR-DAG:   [[i32_8:%[0-9]+\:iid]] = OpConstantI [[i32type]], 8
-; CHECK-MIR-DAG:   [[i32_0:%[0-9]+\:iid]] = OpConstantI [[i32type]], 0
-; CHECK-MIR-DAG:   [[i32_5:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 5
-; CHECK-MIR-DAG:   [[enc_float:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 3
-; CHECK-MIR-DAG:   [[enc_boolean:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 2
+; CHECK-MIR-DAG:   [[i32_8:%[0-9]+\:iid]] = OpConstantI [[i32type]], 8{{$}}
+; CHECK-MIR-DAG:   [[i32_0:%[0-9]+\:pid]] = OpConstantNull
+; CHECK-MIR-DAG:   [[i32_5:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 5{{$}}
+; CHECK-MIR-DAG:   [[enc_float:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 3{{$}}
+; CHECK-MIR-DAG:   [[enc_boolean:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 2{{$}}
 ; CHECK-MIR-DAG:   [[bool:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_8]], [[enc_boolean]], [[i32_0]]
-; CHECK-MIR-DAG:   [[i32_16:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 16
-; CHECK-MIR-DAG:   [[enc_signed:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 4
+; CHECK-MIR-DAG:   [[i32_16:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 16{{$}}
+; CHECK-MIR-DAG:   [[enc_signed:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 4{{$}}
 ; CHECK-MIR-DAG:   [[short:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_16]], [[enc_signed]], [[i32_0]]
 ; CHECK-MIR-DAG:   [[char:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_8]], [[i32_5]], [[i32_0]]
-; CHECK-MIR-DAG:   [[i32_64:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 64
+; CHECK-MIR-DAG:   [[i32_64:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 64{{$}}
 ; CHECK-MIR-DAG:   [[long:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_64]], [[enc_signed]], [[i32_0]]
-; CHECK-MIR-DAG:   [[i32_32:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 32
-; CHECK-MIR-DAG:   [[enc_unsigned:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 6
+; CHECK-MIR-DAG:   [[i32_32:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 32{{$}}
+; CHECK-MIR-DAG:   [[enc_unsigned:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 6{{$}}
 ; CHECK-MIR-DAG:   [[unsigned_int:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_32]], [[enc_unsigned]], [[i32_0]]
 ; CHECK-MIR-DAG:   [[unsigned_short:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_16]], [[enc_unsigned]], [[i32_0]]
-; CHECK-MIR-DAG:   [[enc_unsigned_char:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 7
+; CHECK-MIR-DAG:   [[enc_unsigned_char:%[0-9]+\:iid\(s32\)]] = OpConstantI [[i32type]], 7{{$}}
 ; CHECK-MIR-DAG:   [[unsigned_char:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_8]], [[enc_unsigned_char]], [[i32_0]]
 ; CHECK-MIR-DAG:   [[unsigned_long:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_64]], [[enc_unsigned]], [[i32_0]]
 ; CHECK-MIR-DAG:   [[float:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_32]], [[enc_float]], [[i32_0]]
@@ -43,17 +43,17 @@
 ; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[debug_info_none]], [[i32_5]], [[i32_0]]
 
 ; CHECK-SPIRV:	[[i32type:%[0-9]+]] = OpTypeInt 32 0
-; CHECK-SPIRV-DAG:	[[i32_8:%[0-9]+]] = OpConstant [[i32type]] 8
-; CHECK-SPIRV-DAG:	[[i32_0:%[0-9]+]] = OpConstant [[i32type]] 0
-; CHECK-SPIRV-DAG:	[[i32_5:%[0-9]+]] = OpConstant [[i32type]] 5
-; CHECK-SPIRV-DAG:	[[enc_float:%[0-9]+]] = OpConstant [[i32type]] 3
-; CHECK-SPIRV-DAG:	[[enc_boolean:%[0-9]+]] = OpConstant [[i32type]] 2
-; CHECK-SPIRV-DAG:	[[i32_16:%[0-9]+]] = OpConstant [[i32type]] 16
-; CHECK-SPIRV-DAG:	[[enc_signed:%[0-9]+]] = OpConstant [[i32type]] 4
-; CHECK-SPIRV-DAG:	[[i32_64:%[0-9]+]] = OpConstant [[i32type]] 64
-; CHECK-SPIRV-DAG:	[[i32_32:%[0-9]+]] = OpConstant [[i32type]] 32
-; CHECK-SPIRV-DAG:	[[enc_unsigned:%[0-9]+]] = OpConstant [[i32type]] 6
-; CHECK-SPIRV-DAG:	[[enc_unsigned_char:%[0-9]+]] = OpConstant [[i32type]] 7
+; CHECK-SPIRV-DAG:	[[i32_8:%[0-9]+]] = OpConstant [[i32type]] 8{{$}}
+; CHECK-SPIRV-DAG:	[[i32_0:%[0-9]+]] = OpConstant [[i32type]] 0{{$}}
+; CHECK-SPIRV-DAG:	[[i32_5:%[0-9]+]] = OpConstant [[i32type]] 5{{$}}
+; CHECK-SPIRV-DAG:	[[enc_float:%[0-9]+]] = OpConstant [[i32type]] 3{{$}}
+; CHECK-SPIRV-DAG:	[[enc_boolean:%[0-9]+]] = OpConstant [[i32type]] 2{{$}}
+; CHECK-SPIRV-DAG:	[[i32_16:%[0-9]+]] = OpConstant [[i32type]] 16{{$}}
+; CHECK-SPIRV-DAG:	[[enc_signed:%[0-9]+]] = OpConstant [[i32type]] 4{{$}}
+; CHECK-SPIRV-DAG:	[[i32_64:%[0-9]+]] = OpConstant [[i32type]] 64{{$}}
+; CHECK-SPIRV-DAG:	[[i32_32:%[0-9]+]] = OpConstant [[i32type]] 32{{$}}
+; CHECK-SPIRV-DAG:	[[enc_unsigned:%[0-9]+]] = OpConstant [[i32type]] 6{{$}}
+; CHECK-SPIRV-DAG:	[[enc_unsigned_char:%[0-9]+]] = OpConstant [[i32type]] 7{{$}}
 ; CHECK-SPIRV-DAG:	[[bool:%[0-9]+]] = OpExtInst {{%[0-9]+ %[0-9]+}} DebugTypeBasic {{%[0-9]+}} [[i32_8]] [[enc_boolean]] [[i32_0]]
 ; CHECK-SPIRV-DAG:	[[short:%[0-9]+]] = OpExtInst {{%[0-9]+ %[0-9]+}} DebugTypeBasic {{%[0-9]+}} [[i32_16]] [[enc_signed]] [[i32_0]]
 ; CHECK-SPIRV-DAG:	[[char:%[0-9]+]] = OpExtInst {{%[0-9]+ %[0-9]+}} DebugTypeBasic {{%[0-9]+}} [[i32_8]] [[i32_5]] [[i32_0]]
diff --git a/llvm/test/CodeGen/SPIRV/freeze.ll b/llvm/test/CodeGen/SPIRV/freeze.ll
index fe4335722fe8b..9077d2ede72a9 100644
--- a/llvm/test/CodeGen/SPIRV/freeze.ll
+++ b/llvm/test/CodeGen/SPIRV/freeze.ll
@@ -14,15 +14,12 @@
 ; CHECK-DAG: %[[FloatTy:.*]] = OpTypeFloat 32
 ; CHECK-DAG: %[[ShortTy:.*]] = OpTypeInt 16 0
 ; CHECK-DAG: %[[IntTy:.*]] = OpTypeInt 32 0
-; CHECK-DAG: %[[Undef:.*]] = OpUndef %[[ShortTy]]
+; CHECK-DAG: %[[Undef16:.*]] = OpUndef %[[ShortTy]]
+; CHECK-DAG: %[[Undef32:.*]] = OpUndef %[[IntTy]]
+; CHECK-DAG: %[[UndefFloat:.*]] = OpUndef %[[FloatTy]]
 ; CHECK-DAG: %[[Const100]] = OpConstant %[[IntTy]] 100
-; CHECK-DAG: %[[StaticPoisonIntFreeze]] = OpConstantNull %[[IntTy]]
-; CHECK-DAG: %[[StaticPoisonFloatFreeze]] = OpConstantNull %[[FloatTy]]
 ; CHECK: %[[Arg1]] = OpFunctionParameter %[[FloatTy]]
-; CHECK: %[[NotAStaticPoison]] = OpIAdd %[[ShortTy]] %[[Arg2]] %[[Undef]]
-
-target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
-target triple = "spir64-unknown-unknown"
+; CHECK: %[[NotAStaticPoison]] = OpIAdd %[[ShortTy]] %[[Arg2]] %[[Undef16]]
 
 define spir_func void @foo(float %arg1, i16 %arg2) {
 entry:
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/dot4add_i8packed.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/dot4add_i8packed.ll
index 2ac557b43916b..8715fc324c071 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/dot4add_i8packed.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/dot4add_i8packed.ll
@@ -11,7 +11,7 @@
 
 ; CHECK: %[[#int_32:]] = OpTypeInt 32 0
 ; CHECK-EXP-DAG: %[[#int_8:]] = OpTypeInt 8 0
-; CHECK-EXP-DAG: %[[#zero:]] = OpConstantNull %[[#int_8]]
+; CHECK-EXP-DAG: %[[#zero:]] = OpConstant %[[#int_8]] 0{{$}}
 ; CHECK-EXP-DAG: %[[#eight:]] = OpConstant %[[#int_8]] 8
 ; CHECK-EXP-DAG: %[[#sixteen:]] = OpConstant %[[#int_8]] 16
 ; CHECK-EXP-DAG: %[[#twentyfour:]] = OpConstant %[[#int_8]] 24
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/dot4add_u8packed.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/dot4add_u8packed.ll
index 8acdb7d2ea324..a43d0be9e775b 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/dot4add_u8packed.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/dot4add_u8packed.ll
@@ -11,7 +11,7 @@
 
 ; CHECK: %[[#int_32:]] = OpTypeInt 32 0
 ; CHECK-EXP-DAG: %[[#int_8:]] = OpTypeInt 8 0
-; CHECK-EXP-DAG: %[[#zero:]] = OpConstantNull %[[#int_8]]
+; CHECK-EXP-DAG: %[[#zero:]] = OpConstant %[[#int_8]] 0{{$}}
 ; CHECK-EXP-DAG: %[[#eight:]] = OpConstant %[[#int_8]] 8
 ; CHECK-EXP-DAG: %[[#sixteen:]] = OpConstant %[[#int_8]] 16
 ; CHECK-EXP-DAG: %[[#twentyfour:]] = OpConstant %[[#int_8]] 24
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/StorageImageDynIdx.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/StorageImageDynIdx.ll
index 94ebe74148b95..6a6d810e6babd 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-resources/StorageImageDynIdx.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/StorageImageDynIdx.ll
@@ -1,9 +1,9 @@
 ; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.5-vulkan-library %s -o - | FileCheck %s
 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.5-vulkan-library %s -o - -filetype=obj | spirv-val %}
 
-; CHECK: OpCapability Shader
-; CHECK-NEXT: OpCapability StorageImageArrayDynamicIndexing
-; CHECK-NEXT: OpCapability Image1D
+; CHECK-DAG: OpCapability Shader
+; CHECK-DAG: OpCapability StorageImageArrayDynamicIndexing
+; CHECK-DAG: OpCapability Image1D
 ; CHECK-NOT: OpCapability
 
 ; CHECK-DAG: OpDecorate [[Var:%[0-9]+]] DescriptorSet 3
@@ -14,7 +14,7 @@
 ; CHECK-DAG: [[BufferPtrType:%[0-9]+]] = OpTypePointer UniformConstant [[BufferType]]
 ; CHECK-DAG: [[ArraySize:%[0-9]+]] = OpConstant [[int]] 3
 ; CHECK-DAG: [[One:%[0-9]+]] = OpConstant [[int]] 1
-; CHECK-DAG: [[Zero:%[0-9]+]] = OpConstant [[int]] 0
+; CHECK-DAG: [[Zero:%[0-9]+]] = OpConstant [[int]] 0{{$}}
 ; CHECK-DAG: [[BufferArrayType:%[0-9]+]] = OpTypeArray [[BufferType]] [[ArraySize]]
 ; CHECK-DAG: [[ArrayPtrType:%[0-9]+]] = OpTypePointer UniformConstant [[BufferArrayType]]
 ; CHECK-DAG: [[Var]] = OpVariable [[ArrayPtrType]] UniformConstant
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/StorageImageNonUniformIdx.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/StorageImageNonUniformIdx.ll
index f9466e431c19c..16f3724d5d10a 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-resources/StorageImageNonUniformIdx.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/StorageImageNonUniformIdx.ll
@@ -1,10 +1,10 @@
 ; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.5-vulkan-library %s -o - | FileCheck %s
 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.5-vulkan-library %s -o - -filetype=obj | spirv-val %}
 
-; CHECK: OpCapability Shader
-; CHECK: OpCapability ShaderNonUniformEXT
-; CHECK-NEXT: OpCapability StorageImageArrayNonUniformIndexing
-; CHECK-NEXT: OpCapability Image1D
+; CHECK-DAG: OpCapability Shader
+; CHECK-DAG: OpCapability ShaderNonUniformEXT
+; CHECK-DAG: OpCapability StorageImageArrayNonUniformIndexing
+; CHECK-DAG: OpCapability Image1D
 ; CHECK-NOT: OpCapability
 
 ; CHECK-DAG: OpDecorate [[Var:%[0-9]+]] DescriptorSet 3
@@ -21,7 +21,7 @@
 ; CHECK-DAG: [[BufferPtrType:%[0-9]+]] = OpTypePointer UniformConstant [[BufferType]]
 ; CHECK-DAG: [[ArraySize:%[0-9]+]] = OpConstant [[int]] 3
 ; CHECK-DAG: [[One]] = OpConstant [[int]] 1
-; CHECK-DAG: [[Zero]] = OpConstant [[int]] 0
+; CHECK-DAG: [[Zero]] = OpConstant [[int]] 0{{$}}
 ; CHECK-DAG: [[BufferArrayType:%[0-9]+]] = OpTypeArray [[BufferType]] [[ArraySize]]
 ; CHECK-DAG: [[ArrayPtrType:%[0-9]+]] = OpTypePointer UniformConstant [[BufferArrayType]]
 ; CHECK-DAG: [[Var]] = OpVariable [[ArrayPtrType]] UniformConstant
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/smul.with.overflow.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/smul.with.overflow.ll
index 2281ccf52bbb4..f839774b4f3e3 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/smul.with.overflow.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/smul.with.overflow.ll
@@ -9,10 +9,12 @@
 ; CHECK-DAG: %[[PtrChar:.*]] = OpTypePointer Function %[[Char]]
 ; CHECK-DAG: %[[StructChar:.*]] = OpTypeStruct %[[Char]] %[[Char]]
 ; CHECK-DAG: %[[ZeroChar:.*]] = OpConstant %[[Char]] 0
+; CHECK-DAG: %[[NullChar:.*]] = OpConstantNull %[[Char]]
 ; CHECK-DAG: %[[Int:.*]] = OpTypeInt 32 0
 ; CHECK-DAG: %[[PtrInt:.*]] = OpTypePointer Function %[[Int]]
 ; CHECK-DAG: %[[StructInt:.*]] = OpTypeStruct %[[Int]] %[[Int]]
 ; CHECK-DAG: %[[ZeroInt:.*]] = OpConstant %[[Int]] 0
+; CHECK-DAG: %[[NullInt:.*]] = OpConstantNull %[[Int]]
 ; CHECK-DAG: %[[Bool:.*]] = OpTypeBool
 ; CHECK-DAG: %[[V2Bool:.*]] = OpTypeVector %[[Bool]] 2
 ; CHECK-DAG: %[[Long:.*]] = OpTypeInt 64 0
@@ -28,7 +30,7 @@
 ; CHECK: %[[Struct:.*]] = OpSMulExtended %[[StructChar]] %[[A]] %[[B]]
 ; CHECK: %[[Val:.*]] = OpCompositeExtract %[[Char]] %[[Struct]] 0
 ; CHECK: %[[Over:.*]] = OpCompositeExtract %[[Char]] %[[Struct]] 1
-; CHECK: %[[IsOver:.*]] = OpINotEqual %[[Bool]] %[[Over]] %[[ZeroChar]]
+; CHECK: %[[IsOver:.*]] = OpINotEqual %[[Bool]] %[[Over]] %[[NullChar]]
 ; CHECK: %[[Res:.*]] = OpSelect %[[Char]] %[[IsOver]] %[[ZeroChar]] %[[Val]]
 ; CHECK: OpStore %[[Ptr]] %[[Res]] Aligned 1
 ; CHECK: OpReturn
@@ -49,7 +51,7 @@ entry:
 ; CHECK: %[[Struct2:.*]] = OpSMulExtended %[[StructInt]] %[[B2]] %[[A2]]
 ; CHECK: %[[Val2:.*]] = OpCompositeExtract %[[Int]] %[[Struct2]] 0
 ; CHECK: %[[Over2:.*]] = OpCompositeExtract %[[Int]] %[[Struct2]] 1
-; CHECK: %[[IsOver2:.*]] = OpINotEqual %[[Bool]] %[[Over2]] %[[ZeroInt]]
+; CHECK: %[[IsOver2:.*]] = OpINotEqual %[[Bool]] %[[Over2]] %[[NullInt]]
 ; CHECK: %[[Res2:.*]] = OpSelect %[[Int]] %[[IsOver2]] %[[ZeroInt]] %[[Val2]]
 ; CHECK: OpStore %[[Ptr2]] %[[Res2]] Aligned 4
 ; CHECK: OpReturn
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/uadd.with.overflow.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/uadd.with.overflow.ll
index 1c77800a1630d..fc3e9b6ab3f89 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/uadd.with.overflow.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/uadd.with.overflow.ll
@@ -9,10 +9,12 @@
 ; CHECK-DAG: %[[PtrChar:.*]] = OpTypePointer Function %[[Char]]
 ; CHECK-DAG: %[[StructChar:.*]] = OpTypeStruct %[[Char]] %[[Char]]
 ; CHECK-DAG: %[[ZeroChar:.*]] = OpConstant %[[Char]] 0
+; CHECK-DAG: %[[NullChar:.*]] = OpConstantNull %[[Char]]
 ; CHECK-DAG: %[[Int:.*]] = OpTypeInt 32 0
 ; CHECK-DAG: %[[PtrInt:.*]] = OpTypePointer Function %[[Int]]
 ; CHECK-DAG: %[[StructInt:.*]] = OpTypeStruct %[[Int]] %[[Int]]
 ; CHECK-DAG: %[[ZeroInt:.*]] = OpConstant %[[Int]] 0
+; CHECK-DAG: %[[NullInt:.*]] = OpConstantNull %[[Int]]
 ; CHECK-DAG: %[[Bool:.*]] = OpTypeBool
 ; CHECK-DAG: %[[V2Bool:.*]] = OpTypeVector %[[Bool]] 2
 ; CHECK-DAG: %[[Long:.*]] = OpTypeInt 64 0
@@ -29,7 +31,7 @@
 ; CHECK: %[[Struct:.*]] = OpIAddCarry %[[StructChar]] %[[A]] %[[B]]
 ; CHECK: %[[Val:.*]] = OpCompositeExtract %[[Char]] %[[Struct]] 0
 ; CHECK: %[[Over:.*]] = OpCompositeExtract %[[Char]] %[[Struct]] 1
-; CHECK: %[[IsOver:.*]] = OpINotEqual %[[Bool]] %[[Over]] %[[ZeroChar]]
+; CHECK: %[[IsOver:.*]] = OpINotEqual %[[Bool]] %[[Over]] %[[NullChar]]
 ; CHECK: %[[Res:.*]] = OpSelect %[[Char]] %[[IsOver]] %[[ZeroChar]] %[[Val]]
 ; CHECK: OpStore %[[Ptr]] %[[Res]] Aligned 1
 ; CHECK: OpReturn
@@ -50,7 +52,7 @@ entry:
 ; CHECK: %[[Struct2:.*]] = OpIAddCarry %[[StructInt]] %[[B2]] %[[A2]]
 ; CHECK: %[[Val2:.*]] = OpCompositeExtract %[[Int]] %[[Struct2]] 0
 ; CHECK: %[[Over2:.*]] = OpCompositeExtract %[[Int]] %[[Struct2]] 1
-; CHECK: %[[IsOver2:.*]] = OpINotEqual %[[Bool]] %[[Over2]] %[[ZeroInt]]
+; CHECK: %[[IsOver2:.*]] = OpINotEqual %[[Bool]] %[[Over2]] %[[NullInt]]
 ; CHECK: %[[Res2:.*]] = OpSelect %[[Int]] %[[IsOver2]] %[[ZeroInt]] %[[Val2]]
 ; CHECK: OpStore %[[Ptr2]] %[[Res2]] Aligned 4
 ; CHECK: OpReturn
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/umul.with.overflow.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/umul.with.overflow.ll
index 7113dd692f6ac..e01489d6995f7 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/umul.with.overflow.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/umul.with.overflow.ll
@@ -9,10 +9,12 @@
 ; CHECK-DAG: %[[PtrChar:.*]] = OpTypePointer Function %[[Char]]
 ; CHECK-DAG: %[[StructChar:.*]] = OpTypeStruct %[[Char]] %[[Char]]
 ; CHECK-DAG: %[[ZeroChar:.*]] = OpConstant %[[Char]] 0
+; CHECK-DAG: %[[NullChar:.*]] = OpConstantNull %[[Char]]
 ; CHECK-DAG: %[[Int:.*]] = OpTypeInt 32 0
 ; CHECK-DAG: %[[PtrInt:.*]] = OpTypePointer Function %[[Int]]
 ; CHECK-DAG: %[[StructInt:.*]] = OpTypeStruct %[[Int]] %[[Int]]
 ; CHECK-DAG: %[[ZeroInt:.*]] = OpConstant %[[Int]] 0
+; CHECK-DAG: %[[NullInt:.*]] = OpConstantNull %[[Int]]
 ; CHECK-DAG: %[[Bool:.*]] = OpTypeBool
 ; CHECK-DAG: %[[V2Bool:.*]] = OpTypeVector %[[Bool]] 2
 ; CHECK-DAG: %[[Long:.*]] = OpTypeInt 64 0
@@ -28,7 +30,7 @@
 ; CHECK: %[[Struct:.*]] = OpUMulExtended %[[StructChar]] %[[A]] %[[B]]
 ; CHECK: %[[Val:.*]] = OpCompositeExtract %[[Char]] %[[Struct]] 0
 ; CHECK: %[[Over:.*]] = OpCompositeExtract %[[Char]] %[[Struct]] 1
-; CHECK: %[[IsOver:.*]] = OpINotEqual %[[Bool]] %[[Over]] %[[ZeroChar]]
+; CHECK: %[[IsOver:.*]] = OpINotEqual %[[Bool]] %[[Over]] %[[NullChar]]
 ; CHECK: %[[Res:.*]] = OpSelect %[[Char]] %[[IsOver]] %[[ZeroChar]] %[[Val]]
 ; CHECK: OpStore %[[Ptr]] %[[Res]] Aligned 1
 ; CHECK: OpReturn
@@ -49,7 +51,7 @@ entry:
 ; CHECK: %[[Struct2:.*]] = OpUMulExtended %[[StructInt]] %[[B2]] %[[A2]]
 ; CHECK: %[[Val2:.*]] = OpCompositeExtract %[[Int]] %[[Struct2]] 0
 ; CHECK: %[[Over2:.*]] = OpCompositeExtract %[[Int]] %[[Struct2]] 1
-; CHECK: %[[IsOver2:.*]] = OpINotEqual %[[Bool]] %[[Over2]] %[[ZeroInt]]
+; CHECK: %[[IsOver2:.*]] = OpINotEqual %[[Bool]] %[[Over2]] %[[NullInt]]
 ; CHECK: %[[Res2:.*]] = OpSelect %[[Int]] %[[IsOver2]] %[[ZeroInt]] %[[Val2]]
 ; CHECK: OpStore %[[Ptr2]] %[[Res2]] Aligned 4
 ; CHECK: OpReturn
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/usub.with.overflow.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/usub.with.overflow.ll
index 963dd70f606b6..f7ea655e6529a 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/usub.with.overflow.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/usub.with.overflow.ll
@@ -9,10 +9,12 @@
 ; CHECK-DAG: %[[PtrChar:.*]] = OpTypePointer Function %[[Char]]
 ; CHECK-DAG: %[[StructChar:.*]] = OpTypeStruct %[[Char]] %[[Char]]
 ; CHECK-DAG: %[[ZeroChar:.*]] = OpConstant %[[Char]] 0
+; CHECK-DAG: %[[NullChar:.*]] = OpConstantNull %[[Char]]
 ; CHECK-DAG: %[[Int:.*]] = OpTypeInt 32 0
 ; CHECK-DAG: %[[PtrInt:.*]] = OpTypePointer Function %[[Int]]
 ; CHECK-DAG: %[[StructInt:.*]] = OpTypeStruct %[[Int]] %[[Int]]
 ; CHECK-DAG: %[[ZeroInt:.*]] = OpConstant %[[Int]] 0
+; CHECK-DAG: %[[NullInt:.*]] = OpConstantNull %[[Int]]
 ; CHECK-DAG: %[[Bool:.*]] = OpTypeBool
 ; CHECK-DAG: %[[V2Bool:.*]] = OpTypeVector %[[Bool]] 2
 ; CHECK-DAG: %[[Long:.*]] = OpTypeInt 64 0
@@ -28,7 +30,7 @@
 ; CHECK: %[[Struct:.*]] = OpISubBorrow %[[StructChar]] %[[A]] %[[B]]
 ; CHECK: %[[Val:.*]] = OpCompositeExtract %[[Char]] %[[Struct]] 0
 ; CHECK: %[[Over:.*]] = OpCompositeExtract %[[Char]] %[[Struct]] 1
-; CHECK: %[[IsOver:.*]] = OpINotEqual %[[Bool]] %[[Over]] %[[ZeroChar]]
+; CHECK: %[[IsOver:.*]] = OpINotEqual %[[Bool]] %[[Over]] %[[NullChar]]
 ; CHECK: %[[Res:.*]] = OpSelect %[[Char]] %[[IsOver]] %[[ZeroChar]] %[[Val]]
 ; CHECK: OpStore %[[Ptr]] %[[Res]] Aligned 1
 ; CHECK: OpReturn
@@ -49,7 +51,7 @@ entry:
 ; CHECK: %[[Struct2:.*]] = OpISubBorrow %[[StructInt]] %[[B2]] %[[A2]]
 ; CHECK: %[[Val2:.*]] = OpCompositeExtract %[[Int]] %[[Struct2]] 0
 ; CHECK: %[[Over2:.*]] = OpCompositeExtract %[[Int]] %[[Struct2]] 1
-; CHECK: %[[IsOver2:.*]] = OpINotEqual %[[Bool]] %[[Over2]] %[[ZeroInt]]
+; CHECK: %[[IsOver2:.*]] = OpINotEqual %[[Bool]] %[[Over2]] %[[NullInt]]
 ; CHECK: %[[Res2:.*]] = OpSelect %[[Int]] %[[IsOver2]] %[[ZeroInt]] %[[Val2]]
 ; CHECK: OpStore %[[Ptr2]] %[[Res2]] Aligned 4
 ; CHECK: OpReturn

>From a9cd2191767d844c7e87a5998b0e23d7a249b9bb Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Fri, 14 Mar 2025 10:41:27 -0700
Subject: [PATCH 9/9] experiment with cashes

---
 llvm/lib/Target/SPIRV/SPIRVIRMapping.h        | 67 +++++++++++++------
 llvm/lib/Target/SPIRV/SPIRVInstrInfo.td       |  3 -
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 56 +++++-----------
 llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp   | 13 ++--
 llvm/lib/Target/SPIRV/SPIRVUtils.cpp          |  3 +-
 5 files changed, 65 insertions(+), 77 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVIRMapping.h b/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
index bec2a989483e8..feee13c0b3117 100644
--- a/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
+++ b/llvm/lib/Target/SPIRV/SPIRVIRMapping.h
@@ -26,7 +26,7 @@
 
 namespace llvm {
 namespace SPIRV {
-
+/*
 inline size_t to_hash(const MachineInstr *MI,
                       std::unordered_set<const MachineInstr *> &Visited) {
   if (!MI || !Visited.insert(MI).second)
@@ -47,6 +47,21 @@ inline size_t to_hash(const MachineInstr *MI) {
   std::unordered_set<const MachineInstr *> Visited;
   return to_hash(MI, Visited);
 }
+*/
+
+inline size_t to_hash(const MachineInstr *MI) {
+  hash_code H = llvm::hash_combine(MI->getOpcode(), MI->getNumOperands());
+  for (unsigned I = MI->getNumDefs(); I < MI->getNumOperands(); ++I) {
+    const MachineOperand &MO = MI->getOperand(I);
+    if (MO.getType() == MachineOperand::MO_CImmediate)
+      H = llvm::hash_combine(H, MO.getType(), MO.getCImm());
+    else if (MO.getType() == MachineOperand::MO_FPImmediate)
+      H = llvm::hash_combine(H, MO.getType(), MO.getFPImm());
+    else
+      H = llvm::hash_combine(H, MO.getType());
+  }
+  return H;
+}
 
 using MIHandle = std::pair<const MachineInstr *, size_t>;
 
@@ -169,46 +184,54 @@ inline IRHandle handle(const MachineInstr *KeyMI) {
 // per an LLVM/GlobalISel entity (e.g., Type, Constant, Machine Instruction).
 class SPIRVIRMapping {
   DenseMap<SPIRV::IRHandleMF, SPIRV::MIHandle> Vregs;
-  DenseMap<SPIRV::MIHandle, SPIRV::IRHandle> Defs;
+  DenseMap<const MachineInstr *, SPIRV::IRHandleMF> Defs;
 
 public:
   bool add(SPIRV::IRHandle Handle, const MachineInstr *MI) {
-    if (std::get<1>(Handle) == 17 && std::get<2>(Handle) == 8) {
-      const Value *Ptr = (const Value *)std::get<0>(Handle);
-      if (const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(Ptr)) {
-        if (CI->getZExtValue() == 8 || CI->getZExtValue() == 5) {
-          [[maybe_unused]] uint64_t v = CI->getZExtValue();
-        }
-      }
+    if (auto DefIt = Defs.find(MI); DefIt != Defs.end()) {
+      auto [ExistHandle, ExistMF] = DefIt->second;
+      if (Handle == ExistHandle && MI->getMF() == ExistMF)
+        return false; // already exists
+      // invalidate the record
+      Vregs.erase(DefIt->second);
+      Defs.erase(DefIt);
     }
-    auto MIKey = SPIRV::getMIKey(MI);
-    auto [It, Inserted] =
-        Vregs.try_emplace(std::make_pair(Handle, MI->getMF()), MIKey);
-    if (Inserted) {
-      [[maybe_unused]] auto [_, IsConsistent] =
-          Defs.insert_or_assign(MIKey, Handle);
-      assert(IsConsistent);
+    SPIRV::IRHandleMF HandleMF = SPIRV::getIRHandleMF(Handle, MI->getMF());
+    SPIRV::MIHandle MIKey = SPIRV::getMIKey(MI);
+    auto It1 = Vregs.try_emplace(HandleMF, MIKey);
+    if (!It1.second) {
+      // there is an expired record
+      auto [ExistMI, _] = It1.first->second;
+      // invalidate the record
+      Defs.erase(ExistMI);
+      // update the record
+      It1.first->second = MIKey;
     }
-    return Inserted;
+    [[maybe_unused]] auto It2 = Defs.try_emplace(MI, HandleMF);
+    assert(It2.second);
+    return true;
   }
   bool erase(const MachineInstr *MI) {
     bool Res = false;
-    if (auto It = Defs.find(SPIRV::getMIKey(MI)); It != Defs.end()) {
-      Res = Vregs.erase(SPIRV::getIRHandleMF(It->second, MI->getMF()));
+    if (auto It = Defs.find(MI); It != Defs.end()) {
+      Res = Vregs.erase(It->second);
       Defs.erase(It);
     }
     return Res;
   }
   const MachineInstr *findMI(SPIRV::IRHandle Handle,
                              const MachineFunction *MF) {
-    auto It = Vregs.find(SPIRV::getIRHandleMF(Handle, MF));
+    SPIRV::IRHandleMF HandleMF = SPIRV::getIRHandleMF(Handle, MF);
+    auto It = Vregs.find(HandleMF);
     if (It == Vregs.end())
       return nullptr;
     auto [MI, Hash] = It->second;
-    if (SPIRV::to_hash(MI) != Hash) {
+    assert(SPIRV::to_hash(MI) == Hash);
+    assert(Defs.find(MI) != Defs.end() && Defs.find(MI)->second == HandleMF);
+    /*if (SPIRV::to_hash(MI) != Hash) {
       erase(MI);
       return nullptr;
-    }
+    }*/
     return MI;
   }
   Register find(SPIRV::IRHandle Handle, const MachineFunction *MF) {
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
index 4b9bddd661f63..3499c2340a2dd 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
+++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
@@ -15,7 +15,6 @@ include "SPIRVSymbolicOperands.td"
 
 // Codegen only metadata instructions
 let isCodeGenOnly=1 in {
-  def TYPEREF: Pseudo<(outs), (ins ID:$src_id, TYPE:$src_ty)>;
   def ASSIGN_TYPE: Pseudo<(outs ID:$dst_id), (ins ID:$src_id, TYPE:$src_ty)>;
   def DECL_TYPE: Pseudo<(outs ID:$dst_id), (ins ID:$src_id, TYPE:$src_ty)>;
   def GET_ID: Pseudo<(outs iID:$dst_id), (ins iID:$src)>;
@@ -29,10 +28,8 @@ let isCodeGenOnly=1 in {
 def SPVTypeBin : SDTypeProfile<1, 2, []>;
 
 def assigntype : SDNode<"SPIRVISD::AssignType", SPVTypeBin>;
-def typeref : SDNode<"SPIRVISD::TypeRef", SPVTypeBin>;
 
 def : GINodeEquiv<ASSIGN_TYPE, assigntype>;
-def : GINodeEquiv<TYPEREF, typeref>;
 
 class BinOp<string name, bits<16> opCode, list<dag> pattern=[]>
                 : Op<opCode, (outs ID:$dst), (ins TYPE:$src_ty, ID:$src, ID:$src2),
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 8f1ac07dd9450..64d9a291f637d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -393,26 +393,21 @@ void SPIRVInstructionSelector::resetVRegsType(MachineFunction &MF) {
   }
   for (const auto &MBB : MF) {
     for (const auto &MI : MBB) {
-      if (MI.getOpcode() == SPIRV::ASSIGN_TYPE) {
-        Register DstReg = MI.getOperand(0).getReg();
-        LLT DstType = MRI.getType(DstReg);
-        Register SrcReg = MI.getOperand(1).getReg();
-        LLT SrcType = MRI.getType(SrcReg);
-        if (DstType != SrcType)
-          MRI.setType(DstReg, MRI.getType(SrcReg));
-
-        const TargetRegisterClass *DstRC = MRI.getRegClassOrNull(DstReg);
-        const TargetRegisterClass *SrcRC = MRI.getRegClassOrNull(SrcReg);
-        if (DstRC != SrcRC && SrcRC)
-          MRI.setRegClass(DstReg, SrcRC);
-      } else if (MI.getOpcode() == SPIRV::TYPEREF) {
-        Register DstReg = MI.getOperand(0).getReg();
-        LLT DstType = MRI.getType(DstReg);
-        Register SrcReg = MI.getOperand(1).getReg();
-        LLT SrcType = MRI.getType(SrcReg);
-        if (DstType != SrcType)
-          MRI.setType(DstReg, MRI.getType(SrcReg));
-      }
+      //GR.invalidateMachineInstr(&I);
+      if (MI.getOpcode() != SPIRV::ASSIGN_TYPE)
+        continue;
+
+      Register DstReg = MI.getOperand(0).getReg();
+      LLT DstType = MRI.getType(DstReg);
+      Register SrcReg = MI.getOperand(1).getReg();
+      LLT SrcType = MRI.getType(SrcReg);
+      if (DstType != SrcType)
+        MRI.setType(DstReg, MRI.getType(SrcReg));
+
+      const TargetRegisterClass *DstRC = MRI.getRegClassOrNull(DstReg);
+      const TargetRegisterClass *SrcRC = MRI.getRegClassOrNull(SrcReg);
+      if (DstRC != SrcRC && SrcRC)
+        MRI.setRegClass(DstReg, SrcRC);
     }
   }
 }
@@ -523,27 +518,6 @@ bool SPIRVInstructionSelector::select(MachineInstr &I) {
       GR.invalidateMachineInstr(&I);
       I.removeFromParent();
       return true;
-    } else if (Opcode == SPIRV::TYPEREF) {
-      Register SrcReg = I.getOperand(0).getReg();
-      auto *Def = MRI->getVRegDef(SrcReg);
-      if (isTypeFoldingSupported(Def->getOpcode())) {
-        bool Res = selectImpl(I, *CoverageInfo);
-        LLVM_DEBUG({
-          if (!Res && Def->getOpcode() != TargetOpcode::G_CONSTANT) {
-            dbgs() << "Unexpected pattern in ASSIGN_TYPE.\nInstruction: ";
-            I.print(dbgs());
-          }
-        });
-        assert(Res || Def->getOpcode() == TargetOpcode::G_CONSTANT);
-        if (Res) {
-          if (!isTriviallyDead(*Def, *MRI) && isDead(*Def, *MRI))
-            DeadMIs.insert(Def);
-          return Res;
-        }
-      }
-      GR.invalidateMachineInstr(&I);
-      I.removeFromParent();
-      return true;
     } else if (I.getNumDefs() == 1) {
       // Make all vregs 64 bits (for SPIR-V IDs).
       MRI->setType(I.getOperand(0).getReg(), LLT::scalar(64));
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index 0ece31ee88abe..aea49c6a618cd 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -564,8 +564,7 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
         assert(Def && "Expecting an instruction that defines the register");
         // G_GLOBAL_VALUE already has type info.
         if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
-            Def->getOpcode() != SPIRV::ASSIGN_TYPE &&
-            Def->getOpcode() != SPIRV::TYPEREF)
+            Def->getOpcode() != SPIRV::ASSIGN_TYPE)
           insertAssignInstr(Reg, nullptr, AssignedPtrType, GR, MIB,
                             MF.getRegInfo());
         ToErase.push_back(&MI);
@@ -576,8 +575,7 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
         assert(Def && "Expecting an instruction that defines the register");
         // G_GLOBAL_VALUE already has type info.
         if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
-            Def->getOpcode() != SPIRV::ASSIGN_TYPE &&
-            Def->getOpcode() != SPIRV::TYPEREF)
+            Def->getOpcode() != SPIRV::ASSIGN_TYPE)
           insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
         ToErase.push_back(&MI);
       } else if (MIOp == TargetOpcode::FAKE_USE && MI.getNumOperands() > 0) {
@@ -614,8 +612,7 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
           if (isSpvIntrinsic(UseMI, Intrinsic::spv_assign_type) ||
               isSpvIntrinsic(UseMI, Intrinsic::spv_assign_name))
             continue;
-          if (UseMI.getOpcode() == SPIRV::ASSIGN_TYPE ||
-              UseMI.getOpcode() == SPIRV::TYPEREF)
+          if (UseMI.getOpcode() == SPIRV::ASSIGN_TYPE)
             NeedAssignType = false;
         }
         Type *Ty = nullptr;
@@ -665,9 +662,7 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
             if (!ElemTy) {
               // There may be a case when we already know Reg's type.
               MachineInstr *NextMI = MI.getNextNode();
-              if (!NextMI ||
-                  (NextMI->getOpcode() != SPIRV::ASSIGN_TYPE &&
-                   NextMI->getOpcode() != SPIRV::TYPEREF) ||
+              if (!NextMI || NextMI->getOpcode() != SPIRV::ASSIGN_TYPE ||
                   NextMI->getOperand(1).getReg() != Reg)
                 llvm_unreachable("Unexpected opcode");
             }
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index 6e6125c7bd66d..b101e562051a4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -186,8 +186,7 @@ MachineBasicBlock::iterator getOpVariableMBBIt(MachineInstr &I) {
     if (Opcode == SPIRV::OpFunction || Opcode == SPIRV::OpFunctionParameter) {
       IsHeader = true;
     } else if (IsHeader &&
-               !(Opcode == SPIRV::ASSIGN_TYPE || Opcode == SPIRV::TYPEREF ||
-                 Opcode == SPIRV::OpLabel)) {
+               !(Opcode == SPIRV::ASSIGN_TYPE || Opcode == SPIRV::OpLabel)) {
       ++It;
       break;
     }



More information about the llvm-commits mailing list