[llvm] [SPIR-V] Do not rely on type metadata for ptr element type resolution (PR #82678)

Michal Paszkowski via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 28 04:47:27 PST 2024


https://github.com/michalpaszkowski updated https://github.com/llvm/llvm-project/pull/82678

>From 8b57539336f4dfb94346e45b888cc12b150ae24f Mon Sep 17 00:00:00 2001
From: Michal Paszkowski <michal at paszkowski.org>
Date: Thu, 22 Feb 2024 10:59:39 -0800
Subject: [PATCH] [SPIR-V] Do not rely on type metadata for ptr element type
 resolution

---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp       |  75 +++++++-
 llvm/lib/Target/SPIRV/SPIRVBuiltins.h         |  16 +-
 llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp   |  54 ++++--
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 179 +++++++++++-------
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp |  44 +----
 llvm/lib/Target/SPIRV/SPIRVMetadata.cpp       |   7 -
 llvm/lib/Target/SPIRV/SPIRVMetadata.h         |   1 -
 llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp   |   6 +-
 llvm/lib/Target/SPIRV/SPIRVUtils.cpp          |  42 ++--
 llvm/lib/Target/SPIRV/SPIRVUtils.h            |   7 +-
 .../SPIRV/function/alloca-load-store.ll       |  11 +-
 llvm/test/CodeGen/SPIRV/half_no_extension.ll  |   3 -
 .../undef-nested-composite-store.ll           |  10 +-
 .../undef-simple-composite-store.ll           |  10 +-
 llvm/test/CodeGen/SPIRV/opaque_pointers.ll    |  13 +-
 .../SPIRV/opencl/basic/get_global_offset.ll   |  24 +--
 .../kernel_arg_type_function_metadata.ll      |  12 --
 .../kernel_arg_type_module_metadata.ll        |  16 --
 llvm/test/CodeGen/SPIRV/opencl/vload2.ll      |  20 +-
 llvm/test/CodeGen/SPIRV/opencl/vstore2.ll     |  23 +++
 ...cs-TargetExtType-arg-no-spv_assign_type.ll |  12 ++
 ...insics-no-divergent-spv_assign_ptr_type.ll |  12 ++
 ...Intrinsics-no-duplicate-spv_assign_type.ll |  14 ++
 .../pointers/getelementptr-kernel-arg-char.ll |  20 +-
 ...argument-builtin-vload-type-discrapency.ll |  35 ++++
 ...rgument-pointer-type-deduction-mismatch.ll |  12 ++
 ...ment-pointer-type-deduction-no-metadata.ll |  13 ++
 .../pointers/store-operand-ptr-to-struct.ll   |  19 ++
 ...users.ll => two-bitcast-or-param-users.ll} |  10 +-
 .../SPIRV/pointers/two-subsequent-bitcasts.ll |   7 +-
 llvm/test/CodeGen/SPIRV/sitofp-with-bool.ll   |   5 +-
 .../transcoding/OpenCL/atomic_cmpxchg.ll      |   5 +-
 .../SPIRV/transcoding/OpenCL/atomic_legacy.ll |   5 +-
 .../spirv-private-array-initialization.ll     |   1 -
 llvm/test/CodeGen/SPIRV/uitofp-with-bool.ll   |   5 +-
 35 files changed, 463 insertions(+), 285 deletions(-)
 delete mode 100644 llvm/test/CodeGen/SPIRV/opencl/metadata/kernel_arg_type_function_metadata.ll
 delete mode 100644 llvm/test/CodeGen/SPIRV/opencl/metadata/kernel_arg_type_module_metadata.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/opencl/vstore2.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-TargetExtType-arg-no-spv_assign_type.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-duplicate-spv_assign_type.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/pointers/kernel-argument-builtin-vload-type-discrapency.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-mismatch.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-metadata.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll
 rename llvm/test/CodeGen/SPIRV/pointers/{two-bitcast-users.ll => two-bitcast-or-param-users.ll} (50%)

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index c1bb27322443ff..119a15b5f1bfb9 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -1775,7 +1775,7 @@ static const Type *getMachineInstrType(MachineInstr *MI) {
     return nullptr;
   Type *Ty = getMDOperandAsType(NextMI->getOperand(2).getMetadata(), 0);
   assert(Ty && "Type is expected");
-  return getTypedPtrEltType(Ty);
+  return Ty;
 }
 
 static const Type *getBlockStructType(Register ParamReg,
@@ -1787,7 +1787,7 @@ static const Type *getBlockStructType(Register ParamReg,
   // section 6.12.5 should guarantee that we can do this.
   MachineInstr *MI = getBlockStructInstr(ParamReg, MRI);
   if (MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE)
-    return getTypedPtrEltType(MI->getOperand(1).getGlobal()->getType());
+    return MI->getOperand(1).getGlobal()->getType();
   assert(isSpvIntrinsic(*MI, Intrinsic::spv_alloca) &&
          "Blocks in OpenCL C must be traceable to allocation site");
   return getMachineInstrType(MI);
@@ -2043,7 +2043,8 @@ static bool generateVectorLoadStoreInst(const SPIRV::IncomingCall *Call,
           .addImm(Builtin->Number);
   for (auto Argument : Call->Arguments)
     MIB.addUse(Argument);
-  MIB.addImm(Builtin->ElementCount);
+  if (Builtin->Name.contains("load") && Builtin->ElementCount > 1)
+    MIB.addImm(Builtin->ElementCount);
 
   // Rounding mode should be passed as a last argument in the MI for builtins
   // like "vstorea_halfn_r".
@@ -2179,6 +2180,61 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
   return false;
 }
 
+Type *parseBuiltinCallArgumentBaseType(const StringRef DemangledCall,
+                                       unsigned ArgIdx, LLVMContext &Ctx) {
+  SmallVector<StringRef, 10> BuiltinArgsTypeStrs;
+  StringRef BuiltinArgs =
+      DemangledCall.slice(DemangledCall.find('(') + 1, DemangledCall.find(')'));
+  BuiltinArgs.split(BuiltinArgsTypeStrs, ',', -1, false);
+  if (ArgIdx >= BuiltinArgsTypeStrs.size())
+    return nullptr;
+  StringRef TypeStr = BuiltinArgsTypeStrs[ArgIdx].trim();
+
+  // Parse strings representing OpenCL builtin types.
+  if (hasBuiltinTypePrefix(TypeStr)) {
+    // OpenCL builtin types in demangled call strings have the following format:
+    // e.g. ocl_image2d_ro
+    bool IsOCLBuiltinType = TypeStr.consume_front("ocl_");
+    assert(IsOCLBuiltinType && "Invalid OpenCL builtin prefix");
+
+    // Check if this is pointer to a builtin type and not just pointer
+    // representing a builtin type. In case it is a pointer to builtin type,
+    // this will require additional handling in the method calling
+    // parseBuiltinCallArgumentBaseType(...) as this function only retrieves the
+    // base types.
+    if (TypeStr.ends_with("*"))
+      TypeStr = TypeStr.slice(0, TypeStr.find_first_of(" "));
+
+    return parseBuiltinTypeNameToTargetExtType("opencl." + TypeStr.str() + "_t",
+                                               Ctx);
+  }
+
+  // Parse type name in either "typeN" or "type vector[N]" format, where
+  // N is the number of elements of the vector.
+  Type *BaseType;
+  unsigned VecElts = 0;
+
+  BaseType = parseBasicTypeName(TypeStr, Ctx);
+  if (!BaseType)
+    // Unable to recognize SPIRV type name.
+    return nullptr;
+
+  if (BaseType->isVoidTy())
+    BaseType = Type::getInt8Ty(Ctx);
+
+  // Handle "typeN*" or "type vector[N]*".
+  TypeStr.consume_back("*");
+
+  if (TypeStr.consume_front(" vector["))
+    TypeStr = TypeStr.substr(0, TypeStr.find(']'));
+
+  TypeStr.getAsInteger(10, VecElts);
+  if (VecElts > 0)
+    BaseType = VectorType::get(BaseType, VecElts, false);
+
+  return BaseType;
+}
+
 struct BuiltinType {
   StringRef Name;
   uint32_t Opcode;
@@ -2277,9 +2333,8 @@ static SPIRVType *getSampledImageType(const TargetExtType *OpaqueType,
 }
 
 namespace SPIRV {
-const TargetExtType *
-parseBuiltinTypeNameToTargetExtType(std::string TypeName,
-                                    MachineIRBuilder &MIRBuilder) {
+TargetExtType *parseBuiltinTypeNameToTargetExtType(std::string TypeName,
+                                                   LLVMContext &Context) {
   StringRef NameWithParameters = TypeName;
 
   // Pointers-to-opaque-structs representing OpenCL types are first translated
@@ -2303,7 +2358,7 @@ parseBuiltinTypeNameToTargetExtType(std::string TypeName,
   // Parameterized SPIR-V builtins names follow this format:
   // e.g. %spirv.Image._void_1_0_0_0_0_0_0, %spirv.Pipe._0
   if (!NameWithParameters.contains('_'))
-    return TargetExtType::get(MIRBuilder.getContext(), NameWithParameters);
+    return TargetExtType::get(Context, NameWithParameters);
 
   SmallVector<StringRef> Parameters;
   unsigned BaseNameLength = NameWithParameters.find('_') - 1;
@@ -2313,7 +2368,7 @@ parseBuiltinTypeNameToTargetExtType(std::string TypeName,
   bool HasTypeParameter = !isDigit(Parameters[0][0]);
   if (HasTypeParameter)
     TypeParameters.push_back(parseTypeString(
-        Parameters[0], MIRBuilder.getMF().getFunction().getContext()));
+        Parameters[0], Context));
   SmallVector<unsigned> IntParameters;
   for (unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {
     unsigned IntParameter = 0;
@@ -2323,7 +2378,7 @@ parseBuiltinTypeNameToTargetExtType(std::string TypeName,
            "Invalid format of SPIR-V builtin parameter literal!");
     IntParameters.push_back(IntParameter);
   }
-  return TargetExtType::get(MIRBuilder.getContext(),
+  return TargetExtType::get(Context,
                             NameWithParameters.substr(0, BaseNameLength),
                             TypeParameters, IntParameters);
 }
@@ -2343,7 +2398,7 @@ SPIRVType *lowerBuiltinType(const Type *OpaqueType,
   const TargetExtType *BuiltinType = dyn_cast<TargetExtType>(OpaqueType);
   if (!BuiltinType)
     BuiltinType = parseBuiltinTypeNameToTargetExtType(
-        OpaqueType->getStructName().str(), MIRBuilder);
+        OpaqueType->getStructName().str(), MIRBuilder.getContext());
 
   unsigned NumStartingVRegs = MIRBuilder.getMRI()->getNumVirtRegs();
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.h b/llvm/lib/Target/SPIRV/SPIRVBuiltins.h
index 6f957295464812..649f5bfd1d7c26 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.h
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.h
@@ -38,6 +38,17 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
                                  const SmallVectorImpl<Register> &Args,
                                  SPIRVGlobalRegistry *GR);
 
+/// Parses the provided \p ArgIdx argument base type in the \p DemangledCall
+/// skeleton. A base type is either a basic type (e.g. i32 for int), pointer
+/// element type (e.g. i8 for char*), or builtin type (TargetExtType).
+///
+/// \return LLVM Type or nullptr if unrecognized
+///
+/// \p DemangledCall is the skeleton of the lowered builtin function call.
+/// \p ArgIdx is the index of the argument to parse.
+Type *parseBuiltinCallArgumentBaseType(const StringRef DemangledCall,
+                                       unsigned ArgIdx, LLVMContext &Ctx);
+
 /// Translates a string representing a SPIR-V or OpenCL builtin type to a
 /// TargetExtType that can be further lowered with lowerBuiltinType().
 ///
@@ -45,9 +56,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
 ///
 /// \p TypeName is the full string representation of the SPIR-V or OpenCL
 /// builtin type.
-const TargetExtType *
-parseBuiltinTypeNameToTargetExtType(std::string TypeName,
-                                    MachineIRBuilder &MIRBuilder);
+TargetExtType *parseBuiltinTypeNameToTargetExtType(std::string TypeName,
+                                                   LLVMContext &Context);
 
 /// Handles the translation of the provided special opaque/builtin type \p Type
 /// to SPIR-V type. Generates the corresponding machine instructions for the
diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
index cc438b2bb8d4d7..f9197b805f0637 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
@@ -22,6 +22,8 @@
 #include "SPIRVSubtarget.h"
 #include "SPIRVUtils.h"
 #include "llvm/CodeGen/FunctionLoweringInfo.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
 #include "llvm/Support/ModRef.h"
 
 using namespace llvm;
@@ -157,28 +159,42 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx,
 
   Type *OriginalArgType = getOriginalFunctionType(F)->getParamType(ArgIdx);
 
-  // In case of non-kernel SPIR-V function or already TargetExtType, use the
-  // original IR type.
-  if (F.getCallingConv() != CallingConv::SPIR_KERNEL ||
-      isSpecialOpaqueType(OriginalArgType))
+  // If OriginalArgType is non-pointer, use the OriginalArgType (the type cannot
+  // be legally reassigned later).
+  if (!OriginalArgType->isPointerTy())
     return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual);
 
-  SPIRVType *ResArgType = nullptr;
-  if (MDString *MDKernelArgType = getOCLKernelArgType(F, ArgIdx)) {
-    StringRef MDTypeStr = MDKernelArgType->getString();
-    if (MDTypeStr.ends_with("*"))
-      ResArgType = GR->getOrCreateSPIRVTypeByName(
-          MDTypeStr, MIRBuilder,
-          addressSpaceToStorageClass(
-              OriginalArgType->getPointerAddressSpace()));
-    else if (MDTypeStr.ends_with("_t"))
-      ResArgType = GR->getOrCreateSPIRVTypeByName(
-          "opencl." + MDTypeStr.str(), MIRBuilder,
-          SPIRV::StorageClass::Function, ArgAccessQual);
+  // In case OriginalArgType is of pointer type, there are two possibilities:
+  // 1) This is an OpenCL/SPIR-V builtin type if there is spv_assign_type
+  // intrinsic assigning a TargetExtType.
+  // 2) This is a pointer, try to retrieve pointer element type from a
+  // spv_assign_ptr_type intrinsic or otherwise use default pointer element
+  // type.
+  for (auto User : F.getArg(ArgIdx)->users()) {
+    auto *II = dyn_cast<IntrinsicInst>(User);
+    // Check if this is spv_assign_type assigning OpenCL/SPIR-V builtin type.
+    if (II && II->getIntrinsicID() == Intrinsic::spv_assign_type) {
+      MetadataAsValue *VMD = cast<MetadataAsValue>(II->getOperand(1));
+      Type *BuiltinType =
+          cast<ConstantAsMetadata>(VMD->getMetadata())->getType();
+      assert(BuiltinType->isTargetExtTy() && "Expected TargetExtType");
+      return GR->getOrCreateSPIRVType(BuiltinType, MIRBuilder, ArgAccessQual);
+    }
+
+    // Check if this is spv_assign_ptr_type assigning pointer element type.
+    if (!II || II->getIntrinsicID() != Intrinsic::spv_assign_ptr_type)
+      continue;
+
+    MetadataAsValue *VMD = cast<MetadataAsValue>(II->getOperand(1));
+    SPIRVType *ElementType = GR->getOrCreateSPIRVType(
+        cast<ConstantAsMetadata>(VMD->getMetadata())->getType(), MIRBuilder);
+    return GR->getOrCreateSPIRVPointerType(
+        ElementType, MIRBuilder,
+        addressSpaceToStorageClass(
+            cast<ConstantInt>(II->getOperand(2))->getZExtValue()));
   }
-  return ResArgType ? ResArgType
-                    : GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder,
-                                               ArgAccessQual);
+
+  return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual);
 }
 
 static SPIRV::ExecutionModel::ExecutionModel
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index e32cd50be56e38..c627427bd9c7a0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "SPIRV.h"
+#include "SPIRVBuiltins.h"
 #include "SPIRVMetadata.h"
 #include "SPIRVTargetMachine.h"
 #include "SPIRVUtils.h"
@@ -75,7 +76,11 @@ class SPIRVEmitIntrinsics
   void processInstrAfterVisit(Instruction *I);
   void insertAssignPtrTypeIntrs(Instruction *I);
   void insertAssignTypeIntrs(Instruction *I);
-  void insertPtrCastInstr(Instruction *I);
+  void insertAssignTypeInstrForTargetExtTypes(TargetExtType* AssignedType, Value *V);
+  void replacePointerOperandWithPtrCast(Instruction *I, Value *Pointer,
+                                        Type *ExpectedElementType,
+                                        unsigned OperandToReplace);
+  void insertPtrCastOrAssignTypeInstr(Instruction *I);
   void processGlobalValue(GlobalVariable &GV);
 
 public:
@@ -130,13 +135,6 @@ static void setInsertPointSkippingPhis(IRBuilder<> &B, Instruction *I) {
     B.SetInsertPoint(I);
 }
 
-static bool requireAssignPtrType(Instruction *I) {
-  if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I))
-    return true;
-
-  return false;
-}
-
 static bool requireAssignType(Instruction *I) {
   IntrinsicInst *Intr = dyn_cast<IntrinsicInst>(I);
   if (Intr) {
@@ -269,7 +267,7 @@ Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) {
   // SPIR-V, contrary to LLVM 17+ IR, supports bitcasts between pointers of
   // varying element types. In case of IR coming from older versions of LLVM
   // such bitcasts do not provide sufficient information, should be just skipped
-  // here, and handled in insertPtrCastInstr.
+  // here, and handled in insertPtrCastOrAssignTypeInstr.
   if (I.getType()->isPointerTy()) {
     I.replaceAllUsesWith(Source);
     I.eraseFromParent();
@@ -286,34 +284,37 @@ Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) {
   return NewI;
 }
 
-void SPIRVEmitIntrinsics::insertPtrCastInstr(Instruction *I) {
-  Value *Pointer;
-  Type *ExpectedElementType;
-  unsigned OperandToReplace;
+void SPIRVEmitIntrinsics::insertAssignTypeInstrForTargetExtTypes(
+    TargetExtType *AssignedType, Value *V) {
+  // Do not emit spv_assign_type if the V is of the AssignedType already.
+  if (V->getType() == AssignedType)
+    return;
 
-  StoreInst *SI = dyn_cast<StoreInst>(I);
-  if (SI && F->getCallingConv() == CallingConv::SPIR_KERNEL &&
-      SI->getValueOperand()->getType()->isPointerTy() &&
-      isa<Argument>(SI->getValueOperand())) {
-    Pointer = SI->getValueOperand();
-    ExpectedElementType = IntegerType::getInt8Ty(F->getContext());
-    OperandToReplace = 0;
-  } else if (SI) {
-    Pointer = SI->getPointerOperand();
-    ExpectedElementType = SI->getValueOperand()->getType();
-    OperandToReplace = 1;
-  } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
-    Pointer = LI->getPointerOperand();
-    ExpectedElementType = LI->getType();
-    OperandToReplace = 0;
-  } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
-    Pointer = GEPI->getPointerOperand();
-    ExpectedElementType = GEPI->getSourceElementType();
-    OperandToReplace = 0;
-  } else {
+  // Do not emit spv_assign_type if there is one already targetting V. If the
+  // found spv_assign_type assigns a type different than AssignedType, report an
+  // error. Builtin types cannot be redeclared or casted.
+  for (auto User : V->users()) {
+    auto *II = dyn_cast<IntrinsicInst>(User);
+    if (!II || II->getIntrinsicID() != Intrinsic::spv_assign_type)
+      continue;
+
+    MetadataAsValue *VMD = cast<MetadataAsValue>(II->getOperand(1));
+    Type *BuiltinType = dyn_cast<ConstantAsMetadata>(VMD->getMetadata())->getType();
+    if (BuiltinType != AssignedType)
+      report_fatal_error("Type mismatch " + BuiltinType->getTargetExtName() +
+                             "/" + AssignedType->getTargetExtName() +
+                             " for value " + V->getName(),
+                         false);
     return;
   }
 
+  Constant *Const = UndefValue::get(AssignedType);
+  buildIntrWithMD(Intrinsic::spv_assign_type, {V->getType()}, Const, V, {});
+}
+
+void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
+    Instruction *I, Value *Pointer, Type *ExpectedElementType,
+    unsigned OperandToReplace) {
   // If Pointer is the result of nop BitCastInst (ptr -> ptr), use the source
   // pointer instead. The BitCastInst should be later removed when visited.
   while (BitCastInst *BC = dyn_cast<BitCastInst>(Pointer))
@@ -378,38 +379,76 @@ void SPIRVEmitIntrinsics::insertPtrCastInstr(Instruction *I) {
     return;
   }
 
-  // Do not emit spv_ptrcast if it would cast to the default pointer element
-  // type (i8) of the same address space. In case of OpenCL kernels, make sure
-  // i8 is the pointer element type defined for the given kernel argument.
-  if (ExpectedElementType->isIntegerTy(8) &&
-      F->getCallingConv() != CallingConv::SPIR_KERNEL)
-    return;
+  // // Do not emit spv_ptrcast if it would cast to the default pointer element
+  // // type (i8) of the same address space.
+  // if (ExpectedElementType->isIntegerTy(8))
+  //   return;
 
-  Argument *Arg = dyn_cast<Argument>(Pointer);
-  if (ExpectedElementType->isIntegerTy(8) &&
-      F->getCallingConv() == CallingConv::SPIR_KERNEL && Arg) {
-    MDString *ArgType = getOCLKernelArgType(*Arg->getParent(), Arg->getArgNo());
-    if (ArgType && ArgType->getString().starts_with("uchar*"))
-      return;
-  }
-
-  // If this would be the first spv_ptrcast, the pointer's defining instruction
-  // requires spv_assign_ptr_type and does not already have one, do not emit
-  // spv_ptrcast and emit spv_assign_ptr_type instead.
-  Instruction *PointerDefInst = dyn_cast<Instruction>(Pointer);
-  if (FirstPtrCastOrAssignPtrType && PointerDefInst &&
-      requireAssignPtrType(PointerDefInst)) {
+  // If this would be the first spv_ptrcast, do not emit spv_ptrcast and emit
+  // spv_assign_ptr_type instead.
+  if (FirstPtrCastOrAssignPtrType &&
+      (isa<Instruction>(Pointer) || isa<Argument>(Pointer))) {
     buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {Pointer->getType()},
                     ExpectedElementTypeConst, Pointer,
                     {IRB->getInt32(AddressSpace)});
     return;
-  } else {
-    SmallVector<Type *, 2> Types = {Pointer->getType(), Pointer->getType()};
-    SmallVector<Value *, 2> Args = {Pointer, VMD, IRB->getInt32(AddressSpace)};
-    auto *PtrCastI =
-        IRB->CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
-    I->setOperand(OperandToReplace, PtrCastI);
+  }
+
+  // Emit spv_ptrcast
+  SmallVector<Type *, 2> Types = {Pointer->getType(), Pointer->getType()};
+  SmallVector<Value *, 2> Args = {Pointer, VMD, IRB->getInt32(AddressSpace)};
+  auto *PtrCastI = IRB->CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
+  I->setOperand(OperandToReplace, PtrCastI);
+}
+
+void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I) {
+  // Handle basic instructions:
+  StoreInst *SI = dyn_cast<StoreInst>(I);
+  if (SI && F->getCallingConv() == CallingConv::SPIR_KERNEL &&
+      SI->getValueOperand()->getType()->isPointerTy() &&
+      isa<Argument>(SI->getValueOperand())) {
+    return replacePointerOperandWithPtrCast(
+        I, SI->getValueOperand(), IntegerType::getInt8Ty(F->getContext()), 0);
+  } else if (SI) {
+    return replacePointerOperandWithPtrCast(
+        I, SI->getPointerOperand(), SI->getValueOperand()->getType(), 1);
+  } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
+    return replacePointerOperandWithPtrCast(I, LI->getPointerOperand(),
+                                            LI->getType(), 0);
+  } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
+    return replacePointerOperandWithPtrCast(I, GEPI->getPointerOperand(),
+                                            GEPI->getSourceElementType(), 0);
+  }
+
+  // Handle calls to builtins (non-intrinsics):
+  CallInst *CI = dyn_cast<CallInst>(I);
+  if (!CI || CI->isIndirectCall() || CI->getCalledFunction()->isIntrinsic())
+    return;
+
+  std::string DemangledName =
+      getOclOrSpirvBuiltinDemangledName(CI->getCalledFunction()->getName());
+  if (DemangledName.empty())
     return;
+
+  for (unsigned OpIdx = 0; OpIdx < CI->arg_size(); OpIdx++) {
+    Value *ArgOperand = CI->getArgOperand(OpIdx);
+    if (!isa<PointerType>(ArgOperand->getType()))
+      continue;
+
+    // Constants (nulls/undefs) are handled in insertAssignPtrTypeIntrs()
+    if (!isa<Instruction>(ArgOperand) && !isa<Argument>(ArgOperand))
+      continue;
+
+    Type *ExpectedType = SPIRV::parseBuiltinCallArgumentBaseType(
+        DemangledName, OpIdx, I->getContext());
+    if (!ExpectedType)
+      continue;
+
+    if (ExpectedType->isTargetExtTy())
+      insertAssignTypeInstrForTargetExtTypes(cast<TargetExtType>(ExpectedType),
+                                             ArgOperand);
+    else
+      replacePointerOperandWithPtrCast(CI, ArgOperand, ExpectedType, OpIdx);
   }
 }
 
@@ -551,22 +590,20 @@ void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV) {
 
 void SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I) {
   reportFatalOnTokenType(I);
-  if (I->getType()->isVoidTy() || !requireAssignPtrType(I))
+  if (!I->getType()->isPointerTy() || !requireAssignType(I) ||
+      isa<BitCastInst>(I))
     return;
 
   setInsertPointSkippingPhis(*IRB, I->getNextNode());
 
   Constant *EltTyConst;
-  unsigned AddressSpace = 0;
-  if (auto *AI = dyn_cast<AllocaInst>(I)) {
+  unsigned AddressSpace = I->getType()->getPointerAddressSpace();
+  if (auto *AI = dyn_cast<AllocaInst>(I))
     EltTyConst = UndefValue::get(AI->getAllocatedType());
-    AddressSpace = AI->getAddressSpace();
-  } else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
+  else if (auto *GEP = dyn_cast<GetElementPtrInst>(I))
     EltTyConst = UndefValue::get(GEP->getResultElementType());
-    AddressSpace = GEP->getPointerAddressSpace();
-  } else {
-    llvm_unreachable("Unexpected instruction!");
-  }
+  else if (I->getType()->isPointerTy())
+    EltTyConst = UndefValue::get(IntegerType::getInt8Ty(I->getContext()));
 
   buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()}, EltTyConst, I,
                   {IRB->getInt32(AddressSpace)});
@@ -575,7 +612,7 @@ void SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I) {
 void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I) {
   reportFatalOnTokenType(I);
   Type *Ty = I->getType();
-  if (!Ty->isVoidTy() && requireAssignType(I) && !requireAssignPtrType(I)) {
+  if (!Ty->isVoidTy() && !Ty->isPointerTy() && requireAssignType(I)) {
     setInsertPointSkippingPhis(*IRB, I->getNextNode());
     Type *TypeToAssign = Ty;
     if (auto *II = dyn_cast<IntrinsicInst>(I)) {
@@ -597,7 +634,7 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I) {
       if (isa<UndefValue>(Op) && Op->getType()->isAggregateType())
         buildIntrWithMD(Intrinsic::spv_assign_type, {IRB->getInt32Ty()}, Op,
                         UndefValue::get(IRB->getInt32Ty()), {});
-      else
+      else if (!isa<Instruction>(Op)) // TODO: This case could be removed
         buildIntrWithMD(Intrinsic::spv_assign_type, {Op->getType()}, Op, Op,
                         {});
     }
@@ -673,7 +710,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
   for (auto &I : Worklist) {
     insertAssignPtrTypeIntrs(I);
     insertAssignTypeIntrs(I);
-    insertPtrCastInstr(I);
+    insertPtrCastOrAssignTypeInstr(I);
   }
 
   for (auto *I : Worklist) {
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 47fec745c3f18a..3c172f772606b6 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -944,7 +944,6 @@ SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
 }
 
 // Returns nullptr if unable to recognize SPIRV type name
-// TODO: maybe use tablegen to implement this.
 SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVTypeByName(
     StringRef TypeStr, MachineIRBuilder &MIRBuilder,
     SPIRV::StorageClass::StorageClass SC,
@@ -954,51 +953,18 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVTypeByName(
 
   // Parse strings representing either a SPIR-V or OpenCL builtin type.
   if (hasBuiltinTypePrefix(TypeStr))
-    return getOrCreateSPIRVType(
-        SPIRV::parseBuiltinTypeNameToTargetExtType(TypeStr.str(), MIRBuilder),
-        MIRBuilder, AQ);
+    return getOrCreateSPIRVType(SPIRV::parseBuiltinTypeNameToTargetExtType(
+                                    TypeStr.str(), MIRBuilder.getContext()),
+                                MIRBuilder, AQ);
 
   // Parse type name in either "typeN" or "type vector[N]" format, where
   // N is the number of elements of the vector.
   Type *Ty;
 
-  TypeStr.consume_front("atomic_");
-
-  if (TypeStr.starts_with("void")) {
-    Ty = Type::getVoidTy(Ctx);
-    TypeStr = TypeStr.substr(strlen("void"));
-  } else if (TypeStr.starts_with("bool")) {
-    Ty = Type::getIntNTy(Ctx, 1);
-    TypeStr = TypeStr.substr(strlen("bool"));
-  } else if (TypeStr.starts_with("char") || TypeStr.starts_with("uchar")) {
-    Ty = Type::getInt8Ty(Ctx);
-    TypeStr = TypeStr.starts_with("char") ? TypeStr.substr(strlen("char"))
-                                          : TypeStr.substr(strlen("uchar"));
-  } else if (TypeStr.starts_with("short") || TypeStr.starts_with("ushort")) {
-    Ty = Type::getInt16Ty(Ctx);
-    TypeStr = TypeStr.starts_with("short") ? TypeStr.substr(strlen("short"))
-                                           : TypeStr.substr(strlen("ushort"));
-  } else if (TypeStr.starts_with("int") || TypeStr.starts_with("uint")) {
-    Ty = Type::getInt32Ty(Ctx);
-    TypeStr = TypeStr.starts_with("int") ? TypeStr.substr(strlen("int"))
-                                         : TypeStr.substr(strlen("uint"));
-  } else if (TypeStr.starts_with("long") || TypeStr.starts_with("ulong")) {
-    Ty = Type::getInt64Ty(Ctx);
-    TypeStr = TypeStr.starts_with("long") ? TypeStr.substr(strlen("long"))
-                                          : TypeStr.substr(strlen("ulong"));
-  } else if (TypeStr.starts_with("half")) {
-    Ty = Type::getHalfTy(Ctx);
-    TypeStr = TypeStr.substr(strlen("half"));
-  } else if (TypeStr.starts_with("float")) {
-    Ty = Type::getFloatTy(Ctx);
-    TypeStr = TypeStr.substr(strlen("float"));
-  } else if (TypeStr.starts_with("double")) {
-    Ty = Type::getDoubleTy(Ctx);
-    TypeStr = TypeStr.substr(strlen("double"));
-  } else {
+  Ty = parseBasicTypeName(TypeStr, Ctx);
+  if (!Ty)
     // Unable to recognize SPIRV type name
     return nullptr;
-  }
 
   auto SpirvTy = getOrCreateSPIRVType(Ty, MIRBuilder, AQ);
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp b/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp
index e8c707742f2443..3800aac70df327 100644
--- a/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp
@@ -82,11 +82,4 @@ MDString *getOCLKernelArgTypeQual(const Function &F, unsigned ArgIdx) {
   return getOCLKernelArgAttribute(F, ArgIdx, "kernel_arg_type_qual");
 }
 
-MDString *getOCLKernelArgType(const Function &F, unsigned ArgIdx) {
-  assert(
-      F.getCallingConv() == CallingConv::SPIR_KERNEL &&
-      "Kernel attributes are attached/belong only to OpenCL kernel functions");
-  return getOCLKernelArgAttribute(F, ArgIdx, "kernel_arg_type");
-}
-
 } // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVMetadata.h b/llvm/lib/Target/SPIRV/SPIRVMetadata.h
index 50aee723439592..fb4269457d6dd3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVMetadata.h
+++ b/llvm/lib/Target/SPIRV/SPIRVMetadata.h
@@ -25,7 +25,6 @@ namespace llvm {
 
 MDString *getOCLKernelArgAccessQual(const Function &F, unsigned ArgIdx);
 MDString *getOCLKernelArgTypeQual(const Function &F, unsigned ArgIdx);
-MDString *getOCLKernelArgType(const Function &F, unsigned ArgIdx);
 
 } // namespace llvm
 #endif // LLVM_LIB_TARGET_SPIRV_METADATA_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index cbc16fa986614e..a62dce353b2c8a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -272,8 +272,10 @@ static void generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
             addressSpaceToStorageClass(MI.getOperand(3).getImm()));
         MachineInstr *Def = MRI.getVRegDef(Reg);
         assert(Def && "Expecting an instruction that defines the register");
-        insertAssignInstr(Reg, nullptr, AssignedPtrType, GR, MIB,
-                          MF.getRegInfo());
+        // G_GLOBAL_VALUE already has type info.
+        if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
+          insertAssignInstr(Reg, nullptr, AssignedPtrType, GR, MIB,
+                            MF.getRegInfo());
         ToErase.push_back(&MI);
       } else if (isSpvIntrinsic(MI, Intrinsic::spv_assign_type)) {
         Register Reg = MI.getOperand(1).getReg();
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index 05f766d3ec5483..3a06e803a2ce13 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -328,25 +328,15 @@ std::string getOclOrSpirvBuiltinDemangledName(StringRef Name) {
   return Name.substr(Start, Len).str();
 }
 
-const Type *getTypedPtrEltType(const Type *Ty) {
-  // TODO: This function requires updating following the opaque pointer
-  // migration.
-  return Ty;
-}
-
 bool hasBuiltinTypePrefix(StringRef Name) {
-  if (Name.starts_with("opencl.") || Name.starts_with("spirv."))
+  if (Name.starts_with("opencl.") || Name.starts_with("ocl_") ||
+      Name.starts_with("spirv."))
     return true;
   return false;
 }
 
 bool isSpecialOpaqueType(const Type *Ty) {
-  const StructType *SType = dyn_cast<StructType>(getTypedPtrEltType(Ty));
-  if (SType && SType->hasName())
-    return hasBuiltinTypePrefix(SType->getName());
-
-  if (const TargetExtType *EType =
-          dyn_cast<TargetExtType>(getTypedPtrEltType(Ty)))
+  if (const TargetExtType *EType = dyn_cast<TargetExtType>(Ty))
     return hasBuiltinTypePrefix(EType->getName());
 
   return false;
@@ -365,4 +355,30 @@ bool isEntryPoint(const Function &F) {
 
   return false;
 }
+
+Type *parseBasicTypeName(StringRef TypeName, LLVMContext &Ctx) {
+  TypeName.consume_front("atomic_");
+  if (TypeName.consume_front("void"))
+    return Type::getVoidTy(Ctx);
+  else if (TypeName.consume_front("bool"))
+    return Type::getIntNTy(Ctx, 1);
+  else if (TypeName.consume_front("char") || TypeName.consume_front("uchar"))
+    return Type::getInt8Ty(Ctx);
+  else if (TypeName.consume_front("short") || TypeName.consume_front("ushort"))
+    return Type::getInt16Ty(Ctx);
+  else if (TypeName.consume_front("int") || TypeName.consume_front("uint"))
+    return Type::getInt32Ty(Ctx);
+  else if (TypeName.consume_front("long") || TypeName.consume_front("ulong"))
+    return Type::getInt64Ty(Ctx);
+  else if (TypeName.consume_front("half"))
+    return Type::getHalfTy(Ctx);
+  else if (TypeName.consume_front("float"))
+    return Type::getFloatTy(Ctx);
+  else if (TypeName.consume_front("double"))
+    return Type::getDoubleTy(Ctx);
+
+  // Unable to recognize SPIRV type name
+  return nullptr;
+}
+
 } // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h
index a33dc02f854f58..1730feb055188d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.h
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h
@@ -88,10 +88,6 @@ Type *getMDOperandAsType(const MDNode *N, unsigned I);
 // name, otherwise return an empty string.
 std::string getOclOrSpirvBuiltinDemangledName(StringRef Name);
 
-// If Type is a pointer type and it is not opaque pointer, return its
-// element type, otherwise return Type.
-const Type *getTypedPtrEltType(const Type *Type);
-
 // Check if a string contains a builtin prefix.
 bool hasBuiltinTypePrefix(StringRef Name);
 
@@ -100,5 +96,8 @@ bool isSpecialOpaqueType(const Type *Ty);
 
 // Check if the function is an SPIR-V entry point
 bool isEntryPoint(const Function &F);
+
+// Parse basic scalar type name, substring TypeName, and return LLVM type.
+Type *parseBasicTypeName(StringRef TypeName, LLVMContext &Ctx);
 } // namespace llvm
 #endif // LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H
diff --git a/llvm/test/CodeGen/SPIRV/function/alloca-load-store.ll b/llvm/test/CodeGen/SPIRV/function/alloca-load-store.ll
index c64a708b28ebe4..5c06d65b6b4e61 100644
--- a/llvm/test/CodeGen/SPIRV/function/alloca-load-store.ll
+++ b/llvm/test/CodeGen/SPIRV/function/alloca-load-store.ll
@@ -4,13 +4,11 @@
 ; CHECK-DAG: OpName %[[#FOO:]] "foo"
 ; CHECK-DAG: OpName %[[#GOO:]] "goo"
 
-; CHECK-DAG: %[[#CHAR:]] = OpTypeInt 8
 ; CHECK-DAG: %[[#INT:]] = OpTypeInt 32
 ; CHECK-DAG: %[[#STACK_PTR_INT:]] = OpTypePointer Function %[[#INT]]
 ; CHECK-DAG: %[[#GLOBAL_PTR_INT:]] = OpTypePointer CrossWorkgroup %[[#INT]]
-; CHECK-DAG: %[[#GLOBAL_PTR_CHAR:]] = OpTypePointer CrossWorkgroup %[[#CHAR]]
 ; CHECK-DAG: %[[#FN1:]] = OpTypeFunction %[[#INT]] %[[#INT]]
-; CHECK-DAG: %[[#FN2:]] = OpTypeFunction %[[#INT]] %[[#INT]] %[[#GLOBAL_PTR_CHAR]]
+; CHECK-DAG: %[[#FN2:]] = OpTypeFunction %[[#INT]] %[[#INT]] %[[#GLOBAL_PTR_INT]]
 
 define i32 @bar(i32 %a) {
   %p = alloca i32
@@ -55,10 +53,9 @@ define i32 @goo(i32 %a, ptr addrspace(1) %p) {
 
 ; CHECK: %[[#GOO]] = OpFunction %[[#INT]] None %[[#FN2]]
 ; CHECK: %[[#A:]] = OpFunctionParameter %[[#INT]]
-; CHECK: %[[#P:]] = OpFunctionParameter %[[#GLOBAL_PTR_CHAR]]
+; CHECK: %[[#P:]] = OpFunctionParameter %[[#GLOBAL_PTR_INT]]
 ; CHECK: OpLabel
-; CHECK: %[[#C:]] = OpBitcast %[[#GLOBAL_PTR_INT]] %[[#P]]
-; CHECK: OpStore %[[#C]] %[[#A]]
-; CHECK: %[[#B:]] = OpLoad %[[#INT]] %[[#C]]
+; CHECK: OpStore %[[#P]] %[[#A]]
+; CHECK: %[[#B:]] = OpLoad %[[#INT]] %[[#P]]
 ; CHECK: OpReturnValue %[[#B]]
 ; CHECK: OpFunctionEnd
diff --git a/llvm/test/CodeGen/SPIRV/half_no_extension.ll b/llvm/test/CodeGen/SPIRV/half_no_extension.ll
index 6414b62874bc71..a5b0ec9c92d236 100644
--- a/llvm/test/CodeGen/SPIRV/half_no_extension.ll
+++ b/llvm/test/CodeGen/SPIRV/half_no_extension.ll
@@ -7,9 +7,6 @@
 
 ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
 
-; TODO(#60133): Requires updates following opaque pointer migration.
-; XFAIL: *
-
 ; CHECK-SPIRV:     OpCapability Float16Buffer
 ; CHECK-SPIRV-NOT: OpCapability Float16
 
diff --git a/llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll b/llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll
index 5fa4a7a93ee0b9..7425b303f8a87c 100644
--- a/llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll
+++ b/llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll
@@ -7,12 +7,10 @@
 ; CHECK-DAG: %[[#UNDEF:]] = OpUndef %[[#NESTED_STRUCT]]
 
 ; CHECK: %[[#]] = OpFunction %[[#]] None %[[#]]
-; CHECK-NEXT: %[[#PTR:]] = OpFunctionParameter %[[#]]
-; CHECK-NEXT: %[[#]] = OpLabel
-; CHECK-NEXT: %[[#BC:]] = OpBitcast %[[#]] %[[#PTR]]
-; CHECK-NEXT: OpStore %[[#BC]] %[[#UNDEF]] Aligned 4
-; CHECK-NEXT: OpReturn
-; CHECK-NEXT: OpFunctionEnd
+; CHECK: %[[#]] = OpLabel
+; CHECK: OpStore %[[#]] %[[#UNDEF]] Aligned 4
+; CHECK: OpReturn
+; CHECK: OpFunctionEnd
 
 %struct = type {
   i32,
diff --git a/llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll b/llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll
index 24dad10382ada9..cb2c89be28f1f1 100644
--- a/llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll
+++ b/llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll
@@ -6,12 +6,10 @@
 ; CHECK-DAG: %[[#UNDEF:]] = OpUndef %[[#STRUCT]]
 
 ; CHECK: %[[#]] = OpFunction %[[#]] None %[[#]]
-; CHECK-NEXT: %[[#PTR:]] = OpFunctionParameter %[[#]]
-; CHECK-NEXT: %[[#]] = OpLabel
-; CHECK-NEXT: %[[#BC:]] = OpBitcast %[[#]] %[[#PTR]]
-; CHECK-NEXT: OpStore %[[#BC]] %[[#UNDEF]] Aligned 4
-; CHECK-NEXT: OpReturn
-; CHECK-NEXT: OpFunctionEnd
+; CHECK: %[[#]] = OpLabel
+; CHECK: OpStore %[[#]] %[[#UNDEF]] Aligned 4
+; CHECK: OpReturn
+; CHECK: OpFunctionEnd
 
 define void @foo(ptr %ptr) {
   store { i32, i16 } undef, ptr %ptr
diff --git a/llvm/test/CodeGen/SPIRV/opaque_pointers.ll b/llvm/test/CodeGen/SPIRV/opaque_pointers.ll
index 30c9d8dc774e24..db4d1b130b8523 100644
--- a/llvm/test/CodeGen/SPIRV/opaque_pointers.ll
+++ b/llvm/test/CodeGen/SPIRV/opaque_pointers.ll
@@ -1,19 +1,16 @@
 ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK
 
-; CHECK-DAG: %[[#Int8Ty:]] = OpTypeInt 8 0
-; CHECK-DAG: %[[#PtrInt8Ty:]] = OpTypePointer Function %[[#Int8Ty]]
 ; CHECK-DAG: %[[#Int32Ty:]] = OpTypeInt 32 0
 ; CHECK-DAG: %[[#PtrInt32Ty:]] = OpTypePointer Function %[[#Int32Ty]]
 ; CHECK-DAG: %[[#Int64Ty:]] = OpTypeInt 64 0
 ; CHECK-DAG: %[[#PtrInt64Ty:]] = OpTypePointer Function %[[#Int64Ty]]
-; CHECK-DAG: %[[#FTy:]] = OpTypeFunction %[[#Int64Ty]] %[[#PtrInt8Ty]]
+; CHECK-DAG: %[[#FTy:]] = OpTypeFunction %[[#Int64Ty]] %[[#PtrInt32Ty]]
 ; CHECK-DAG: %[[#Const:]] = OpConstant %[[#Int32Ty]] 0
 ; CHECK: OpFunction %[[#Int64Ty]] None %[[#FTy]]
-; CHECK: %[[#Parm:]] = OpFunctionParameter %[[#PtrInt8Ty]]
-; CHECK-DAG: %[[#Bitcast1:]] = OpBitcast %[[#PtrInt32Ty]] %[[#Parm]]
-; CHECK: OpStore %[[#Bitcast1]] %[[#Const]] Aligned 4
-; CHECK-DAG: %[[#Bitcast2:]] = OpBitcast %[[#PtrInt64Ty]] %[[#Parm]]
-; CHECK: %[[#Res:]] = OpLoad %[[#Int64Ty]] %[[#Bitcast2]] Aligned 4
+; CHECK: %[[#Param:]] = OpFunctionParameter %[[#PtrInt32Ty]]
+; CHECK: OpStore %[[#Param]] %[[#Const]] Aligned 4
+; CHECK-DAG: %[[#Bitcast:]] = OpBitcast %[[#PtrInt64Ty]] %[[#Param]]
+; CHECK: %[[#Res:]] = OpLoad %[[#Int64Ty]] %[[#Bitcast]] Aligned 4
 ; CHECK: OpReturnValue %[[#Res]]
 
 define i64 @test(ptr %p) {
diff --git a/llvm/test/CodeGen/SPIRV/opencl/basic/get_global_offset.ll b/llvm/test/CodeGen/SPIRV/opencl/basic/get_global_offset.ll
index 43d6238360f6fc..46a7cf42494261 100644
--- a/llvm/test/CodeGen/SPIRV/opencl/basic/get_global_offset.ll
+++ b/llvm/test/CodeGen/SPIRV/opencl/basic/get_global_offset.ll
@@ -1,22 +1,18 @@
 ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
 
-; CHECK: OpEntryPoint Kernel %[[#test_func:]] "test"
-; CHECK: OpDecorate %[[#f2_decl:]] LinkageAttributes "BuiltInGlobalOffset" Import
-; CHECK: %[[#int_ty:]] = OpTypeInt 8 0
-; CHECK: %[[#void_ty:]] = OpTypeVoid
-; CHECK: %[[#iptr_ty:]] = OpTypePointer CrossWorkgroup  %[[#int_ty]]
-; CHECK: %[[#func_ty:]] = OpTypeFunction %[[#void_ty]] %[[#iptr_ty]]
-; CHECK: %[[#int64_ty:]] = OpTypeInt 64 0
-; CHECK: %[[#vec_ty:]] = OpTypeVector %[[#int64_ty]] 3
-; CHECK: %[[#func2_ty:]] = OpTypeFunction %[[#vec_ty]]
-; CHECK: %[[#int32_ty:]] = OpTypeInt 32 0
-; CHECK: %[[#i32ptr_ty:]] = OpTypePointer CrossWorkgroup  %[[#int32_ty]]
+; CHECK-DAG: OpEntryPoint Kernel %[[#test_func:]] "test"
+; CHECK-DAG: OpDecorate %[[#f2_decl:]] LinkageAttributes "BuiltInGlobalOffset" Import
+; CHECK-DAG: %[[#int32_ty:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#i32ptr_ty:]] = OpTypePointer CrossWorkgroup  %[[#int32_ty]]
+; CHECK-DAG: %[[#void_ty:]] = OpTypeVoid
+; CHECK-DAG: %[[#func_ty:]] = OpTypeFunction %[[#void_ty]] %[[#i32ptr_ty]]
+; CHECK-DAG: %[[#int64_ty:]] = OpTypeInt 64 0
+; CHECK-DAG: %[[#vec_ty:]] = OpTypeVector %[[#int64_ty]] 3
+; CHECK-DAG: %[[#func2_ty:]] = OpTypeFunction %[[#vec_ty]]
 ;; TODO: add 64-bit constant defs
-; CHECK: %[[#f2_decl]] = OpFunction %[[#vec_ty]] Pure %[[#func2_ty]]
+; CHECK-DAG: %[[#f2_decl]] = OpFunction %[[#vec_ty]] Pure %[[#func2_ty]]
 ; CHECK: OpFunctionEnd
 ;; Check that the function register name does not match other registers
-; CHECK-NOT: %[[#int_ty]] = OpFunction
-; CHECK-NOT: %[[#iptr_ty]] = OpFunction
 ; CHECK-NOT: %[[#void_ty]] = OpFunction
 ; CHECK-NOT: %[[#func_ty]] = OpFunction
 ; CHECK-NOT: %[[#int64_ty]] = OpFunction
diff --git a/llvm/test/CodeGen/SPIRV/opencl/metadata/kernel_arg_type_function_metadata.ll b/llvm/test/CodeGen/SPIRV/opencl/metadata/kernel_arg_type_function_metadata.ll
deleted file mode 100644
index ce5910efc6ccd4..00000000000000
--- a/llvm/test/CodeGen/SPIRV/opencl/metadata/kernel_arg_type_function_metadata.ll
+++ /dev/null
@@ -1,12 +0,0 @@
-; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
-
-; CHECK: %[[#TypeSampler:]] = OpTypeSampler
-define spir_kernel void @foo(i64 %sampler) !kernel_arg_addr_space !7 !kernel_arg_access_qual !8 !kernel_arg_type !9 !kernel_arg_type_qual !10 !kernel_arg_base_type !9 {
-entry:
-  ret void
-}
-
-!7 = !{i32 0}
-!8 = !{!"none"}
-!9 = !{!"sampler_t"}
-!10 = !{!""}
diff --git a/llvm/test/CodeGen/SPIRV/opencl/metadata/kernel_arg_type_module_metadata.ll b/llvm/test/CodeGen/SPIRV/opencl/metadata/kernel_arg_type_module_metadata.ll
deleted file mode 100644
index b5bb8433321daf..00000000000000
--- a/llvm/test/CodeGen/SPIRV/opencl/metadata/kernel_arg_type_module_metadata.ll
+++ /dev/null
@@ -1,16 +0,0 @@
-; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
-
-; CHECK: %[[#TypeSampler:]] = OpTypeSampler
-define spir_kernel void @foo(i64 %sampler) {
-entry:
-  ret void
-}
-!opencl.kernels = !{!0}
-
-!0 = !{void (i64)* @foo, !1, !2, !3, !4, !5, !6}
-!1 = !{!"kernel_arg_addr_space", i32 0}
-!2 = !{!"kernel_arg_access_qual", !"none"}
-!3 = !{!"kernel_arg_type", !"sampler_t"}
-!4 = !{!"kernel_arg_type_qual", !""}
-!5 = !{!"kernel_arg_base_type", !"sampler_t"}
-!6 = !{!"kernel_arg_name", !"sampler"}
diff --git a/llvm/test/CodeGen/SPIRV/opencl/vload2.ll b/llvm/test/CodeGen/SPIRV/opencl/vload2.ll
index b219aebc29befe..592de33d4d3938 100644
--- a/llvm/test/CodeGen/SPIRV/opencl/vload2.ll
+++ b/llvm/test/CodeGen/SPIRV/opencl/vload2.ll
@@ -15,20 +15,28 @@
 ; CHECK-DAG: %[[#VINT64:]] = OpTypeVector %[[#INT64]] 2
 ; CHECK-DAG: %[[#VFLOAT:]] = OpTypeVector %[[#FLOAT]] 2
 ; CHECK-DAG: %[[#PTRINT8:]] = OpTypePointer CrossWorkgroup %[[#INT8]]
+; CHECK-DAG: %[[#PTRINT16:]] = OpTypePointer CrossWorkgroup %[[#INT16]]
+; CHECK-DAG: %[[#PTRINT32:]] = OpTypePointer CrossWorkgroup %[[#INT32]]
+; CHECK-DAG: %[[#PTRINT64:]] = OpTypePointer CrossWorkgroup %[[#INT64]]
+; CHECK-DAG: %[[#PTRFLOAT:]] = OpTypePointer CrossWorkgroup %[[#FLOAT]]
 
 ; CHECK: %[[#OFFSET:]] = OpFunctionParameter %[[#INT64]]
-; CHECK: %[[#ADDRESS:]] = OpFunctionParameter %[[#PTRINT8]]
 
 define spir_kernel void @test_fn(i64 %offset, ptr addrspace(1) %address) {
-; CHECK: %[[#]] = OpExtInst %[[#VINT8]] %[[#IMPORT]] vloadn %[[#OFFSET]] %[[#ADDRESS]] 2
+; CHECK: %[[#CASTorPARAMofPTRI8:]] = {{OpBitcast|OpFunctionParameter}}{{.*}}%[[#PTRINT8]]{{.*}}
+; CHECK: %[[#]] = OpExtInst %[[#VINT8]] %[[#IMPORT]] vloadn %[[#OFFSET]] %[[#CASTorPARAMofPTRI8]] 2
   %call1 = call spir_func <2 x i8> @_Z6vload2mPU3AS1Kc(i64 %offset, ptr addrspace(1) %address)
-; CHECK: %[[#]] = OpExtInst %[[#VINT16]] %[[#IMPORT]] vloadn %[[#OFFSET]] %[[#ADDRESS]] 2
+; CHECK: %[[#CASTorPARAMofPTRI16:]] = {{OpBitcast|OpFunctionParameter}}{{.*}}%[[#PTRINT16]]{{.*}}
+; CHECK: %[[#]] = OpExtInst %[[#VINT16]] %[[#IMPORT]] vloadn %[[#OFFSET]] %[[#CASTorPARAMofPTRI16]] 2
   %call2 = call spir_func <2 x i16> @_Z6vload2mPU3AS1Ks(i64 %offset, ptr addrspace(1) %address)
-; CHECK: %[[#]] = OpExtInst %[[#VINT32]] %[[#IMPORT]] vloadn %[[#OFFSET]] %[[#ADDRESS]] 2
+; CHECK: %[[#CASTorPARAMofPTRI32:]] = {{OpBitcast|OpFunctionParameter}}{{.*}}%[[#PTRINT32]]{{.*}}
+; CHECK: %[[#]] = OpExtInst %[[#VINT32]] %[[#IMPORT]] vloadn %[[#OFFSET]] %[[#CASTorPARAMofPTRI32]] 2
   %call3 = call spir_func <2 x i32> @_Z6vload2mPU3AS1Ki(i64 %offset, ptr addrspace(1) %address)
-; CHECK: %[[#]] = OpExtInst %[[#VINT64]] %[[#IMPORT]] vloadn %[[#OFFSET]] %[[#ADDRESS]] 2
+; CHECK: %[[#CASTorPARAMofPTRI64:]] = {{OpBitcast|OpFunctionParameter}}{{.*}}%[[#PTRINT64]]{{.*}}
+; CHECK: %[[#]] = OpExtInst %[[#VINT64]] %[[#IMPORT]] vloadn %[[#OFFSET]] %[[#CASTorPARAMofPTRI64]] 2
   %call4 = call spir_func <2 x i64> @_Z6vload2mPU3AS1Kl(i64 %offset, ptr addrspace(1) %address)
-; CHECK: %[[#]] = OpExtInst %[[#VFLOAT]] %[[#IMPORT]] vloadn %[[#OFFSET]] %[[#ADDRESS]] 2
+; CHECK: %[[#CASTorPARAMofPTRFLOAT:]] = {{OpBitcast|OpFunctionParameter}}{{.*}}%[[#PTRFLOAT]]{{.*}}
+; CHECK: %[[#]] = OpExtInst %[[#VFLOAT]] %[[#IMPORT]] vloadn %[[#OFFSET]] %[[#CASTorPARAMofPTRFLOAT]] 2
   %call5 = call spir_func <2 x float> @_Z6vload2mPU3AS1Kf(i64 %offset, ptr addrspace(1) %address)
   ret void
 }
diff --git a/llvm/test/CodeGen/SPIRV/opencl/vstore2.ll b/llvm/test/CodeGen/SPIRV/opencl/vstore2.ll
new file mode 100644
index 00000000000000..0ea14c7f25e877
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/opencl/vstore2.ll
@@ -0,0 +1,23 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; This test only intends to check the vstoren builtin name resolution.
+; The calls to the OpenCL builtins are not valid and will not pass SPIR-V validation.
+
+; CHECK-DAG: %[[#IMPORT:]] = OpExtInstImport "OpenCL.std"
+
+; CHECK-DAG: %[[#VOID:]] = OpTypeVoid
+; CHECK-DAG: %[[#INT8:]] = OpTypeInt 8 0
+; CHECK-DAG: %[[#INT64:]] = OpTypeInt 64 0
+; CHECK-DAG: %[[#VINT8:]] = OpTypeVector %[[#INT8]] 2
+; CHECK-DAG: %[[#PTRINT8:]] = OpTypePointer CrossWorkgroup %[[#INT8]]
+
+; CHECK: %[[#DATA:]] = OpFunctionParameter %[[#VINT8]]
+; CHECK: %[[#OFFSET:]] = OpFunctionParameter %[[#INT64]]
+; CHECK: %[[#ADDRESS:]] = OpFunctionParameter %[[#PTRINT8]]
+
+define spir_kernel void @test_fn(<2 x i8> %data, i64 %offset, ptr addrspace(1) %address) {
+; CHECK: %[[#]] = OpExtInst %[[#VOID]] %[[#IMPORT]] vstoren %[[#DATA]] %[[#OFFSET]] %[[#ADDRESS]]
+  call spir_func void @_Z7vstore2Dv2_cmPU3AS1c(<2 x i8> %data, i64 %offset, ptr addrspace(1) %address)
+  ret void
+}
+
+declare spir_func void @_Z7vstore2Dv2_cmPU3AS1c(<2 x i8>, i64, ptr addrspace(1))
diff --git a/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-TargetExtType-arg-no-spv_assign_type.ll b/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-TargetExtType-arg-no-spv_assign_type.ll
new file mode 100644
index 00000000000000..d6cdcd7e20e8f2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-TargetExtType-arg-no-spv_assign_type.ll
@@ -0,0 +1,12 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -print-after-all -o - 2>&1 | FileCheck %s
+
+; CHECK: *** IR Dump After SPIRV emit intrinsics (emit-intrinsics) ***
+
+define spir_kernel void @test(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) %srcimg) {
+; CHECK-NOT: call void @llvm.spv.assign.type.p1(ptr addrspace(1) %srcimg, metadata target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) undef)
+  %call = call spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_ro(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) %srcimg)
+  ret void
+; CHECK: }
+}
+
+declare spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_ro(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0))
diff --git a/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll b/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll
new file mode 100644
index 00000000000000..f728eda079860d
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll
@@ -0,0 +1,12 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -print-after-all -o - 2>&1 | FileCheck %s
+
+; CHECK: *** IR Dump After SPIRV emit intrinsics (emit-intrinsics) ***
+
+define spir_kernel void @test_pointer_cast(ptr addrspace(1) %src) {
+; CHECK-NOT: call void @llvm.spv.assign.ptr.type.p1(ptr addrspace(1) %src, metadata i8 undef, i32 1)
+; CHECK: call void @llvm.spv.assign.ptr.type.p1(ptr addrspace(1) %src, metadata i32 0, i32 1)
+  %b = bitcast ptr addrspace(1) %src to ptr addrspace(1)
+  %g = getelementptr inbounds i32, ptr addrspace(1) %b, i64 52
+  ret void
+; CHECK: }
+}
diff --git a/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-duplicate-spv_assign_type.ll b/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-duplicate-spv_assign_type.ll
new file mode 100644
index 00000000000000..7056b9cb1230dc
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-duplicate-spv_assign_type.ll
@@ -0,0 +1,14 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -print-after-all -o - 2>&1 | FileCheck %s
+
+; CHECK: *** IR Dump After SPIRV emit intrinsics (emit-intrinsics) ***
+
+define spir_kernel void @test(ptr addrspace(1) %srcimg) {
+; CHECK: call void @llvm.spv.assign.type.p1(ptr addrspace(1) %srcimg, metadata target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) undef)
+  %call1 = call spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_ro(ptr addrspace(1) %srcimg)
+; CHECK-NOT: call void @llvm.spv.assign.type.p1(ptr addrspace(1) %srcimg, metadata target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) undef)
+  %call2 = call spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_ro(ptr addrspace(1) %srcimg)
+  ret void
+; CHECK: }
+}
+
+declare spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_ro(ptr addrspace(1))
diff --git a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-kernel-arg-char.ll b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-kernel-arg-char.ll
index cca71d409d258d..d2a65917bfd659 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-kernel-arg-char.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-kernel-arg-char.ll
@@ -4,28 +4,20 @@
 
 ; CHECK-DAG: %[[#INT8:]] = OpTypeInt 8 0
 ; CHECK-DAG: %[[#INT64:]] = OpTypeInt 64 0
-; CHECK-DAG: %[[#VINT8:]] = OpTypeVector %[[#INT8]] 2
 ; CHECK-DAG: %[[#PTRINT8:]] = OpTypePointer Workgroup %[[#INT8]]
-; CHECK-DAG: %[[#PTRVINT8:]] = OpTypePointer Workgroup %[[#VINT8]]
 ; CHECK-DAG: %[[#CONST:]] = OpConstant %[[#INT64]] 1
 
-; CHECK: %[[#PARAM1:]] = OpFunctionParameter %[[#PTRVINT8]]
-define spir_kernel void @test1(ptr addrspace(3) %address) !kernel_arg_type !1 {
-; CHECK: %[[#BITCAST1:]] = OpBitcast %[[#PTRINT8]] %[[#PARAM1]]
-; CHECK: %[[#]] = OpInBoundsPtrAccessChain %[[#PTRINT8]] %[[#BITCAST1]] %[[#CONST]]
+; CHECK: %[[#PARAM1:]] = OpFunctionParameter %[[#PTRINT8]]
+define spir_kernel void @test1(ptr addrspace(3) %address) {
+; CHECK: %[[#]] = OpInBoundsPtrAccessChain %[[#PTRINT8]] %[[#PARAM1]] %[[#CONST]]
   %cast = bitcast ptr addrspace(3) %address to ptr addrspace(3)
   %gep = getelementptr inbounds i8, ptr addrspace(3) %cast, i64 1
   ret void
 }
 
-; CHECK: %[[#PARAM2:]] = OpFunctionParameter %[[#PTRVINT8]]
-define spir_kernel void @test2(ptr addrspace(3) %address) !kernel_arg_type !1 {
-; CHECK: %[[#BITCAST2:]] = OpBitcast %[[#PTRINT8]] %[[#PARAM2]]
-; CHECK: %[[#]] = OpInBoundsPtrAccessChain %[[#PTRINT8]] %[[#BITCAST2]] %[[#CONST]]
+; CHECK: %[[#PARAM2:]] = OpFunctionParameter %[[#PTRINT8]]
+define spir_kernel void @test2(ptr addrspace(3) %address) {
+; CHECK: %[[#]] = OpInBoundsPtrAccessChain %[[#PTRINT8]] %[[#PARAM2]] %[[#CONST]]
   %gep = getelementptr inbounds i8, ptr addrspace(3) %address, i64 1
   ret void
 }
-
-declare spir_func <2 x i8> @_Z6vload2mPU3AS3Kc(i64, ptr addrspace(3))
-
-!1 = !{!"char2*"}
diff --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-builtin-vload-type-discrapency.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-builtin-vload-type-discrapency.ll
new file mode 100644
index 00000000000000..b4948b66aed86d
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-builtin-vload-type-discrapency.ll
@@ -0,0 +1,35 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: %[[#INT8:]] = OpTypeInt 8 0
+; CHECK-DAG: %[[#PTRINT8:]] = OpTypePointer CrossWorkgroup %[[#INT8]]
+
+define spir_kernel void @test_fn(ptr addrspace(1) %src) !kernel_arg_addr_space !1 !kernel_arg_access_qual !2 !kernel_arg_type !3 !kernel_arg_type_qual !4 !kernel_arg_base_type !3 {
+entry:
+  %g1 = call spir_func i64 @_Z13get_global_idj(i32 0)
+  %i1 = insertelement <3 x i64> undef, i64 %g1, i32 0
+  %g2 = call spir_func i64 @_Z13get_global_idj(i32 1)
+  %i2 = insertelement <3 x i64> %i1, i64 %g2, i32 1
+  %g3 = call spir_func i64 @_Z13get_global_idj(i32 2)
+  %i3 = insertelement <3 x i64> %i2, i64 %g3, i32 2
+  %e = extractelement <3 x i64> %i3, i32 0
+  %c1 = trunc i64 %e to i32
+  %c2 = sext i32 %c1 to i64
+  %b = bitcast ptr addrspace(1) %src to ptr addrspace(1)
+
+; Make sure that builtin call directly uses either a OpBitcast or OpFunctionParameter of i8* type
+; CHECK: %[[#BITCASTorPARAMETER:]] = {{OpBitcast|OpFunctionParameter}}{{.*}}%[[#PTRINT8]]{{.*}}
+; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] vloadn %[[#]] %[[#BITCASTorPARAMETER]] 3
+  %call = call spir_func <3 x i8> @_Z6vload3mPU3AS1Kc(i64 %c2, ptr addrspace(1) %b)
+
+  ret void
+}
+
+declare spir_func i64 @_Z13get_global_idj(i32)
+
+declare spir_func <3 x i8> @_Z6vload3mPU3AS1Kc(i64, ptr addrspace(1))
+
+!1 = !{i32 1}
+!2 = !{!"none"}
+!3 = !{!"char3*"}
+!4 = !{!""}
diff --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-mismatch.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-mismatch.ll
new file mode 100644
index 00000000000000..46e315b2dc62a2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-mismatch.ll
@@ -0,0 +1,12 @@
+; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o - 2>&1 | FileCheck %s
+
+; CHECK: LLVM ERROR: Type mismatch {{.*}}
+
+define spir_kernel void @test(ptr addrspace(1) %srcimg) {
+  %call1 = call spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_ro(ptr addrspace(1) %srcimg)
+  %call2 = call spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_rw(ptr addrspace(1) %srcimg)
+  ret void
+}
+
+declare spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_ro(ptr addrspace(1))
+declare spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_rw(ptr addrspace(1))
diff --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-metadata.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-metadata.ll
new file mode 100644
index 00000000000000..a513d103970663
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-metadata.ll
@@ -0,0 +1,13 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+define spir_kernel void @test(ptr addrspace(1) %srcimg) {
+; CHECK: %[[#VOID:]] = OpTypeVoid
+; CHECK: %[[#IMAGE:]] = OpTypeImage %[[#VOID]] 2D 0 0 0 0 Unknown ReadOnly
+; CHECK: %[[#PARAM:]] = OpFunctionParameter %[[#IMAGE]]
+; CHECK: %[[#]] = OpImageQuerySizeLod %[[#]] %[[#PARAM]] %[[#]]
+  %call = call spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_ro(ptr addrspace(1) %srcimg)
+  ret void
+}
+
+declare spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_ro(ptr addrspace(1))
diff --git a/llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll b/llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll
new file mode 100644
index 00000000000000..00b03c08e7bbcd
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll
@@ -0,0 +1,19 @@
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+
+; TODO: OpFunctionParameter should be a pointer of struct base type.
+; XFAIL: *
+
+%struct = type {
+  i32,
+  i16
+}
+
+%nested_struct = type {
+  %struct,
+  i16
+}
+
+define void @foo(ptr %ptr) {
+  store %nested_struct undef, ptr %ptr
+  ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-users.ll b/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-or-param-users.ll
similarity index 50%
rename from llvm/test/CodeGen/SPIRV/pointers/two-bitcast-users.ll
rename to llvm/test/CodeGen/SPIRV/pointers/two-bitcast-or-param-users.ll
index f4ea710fa04317..52180d53740883 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-users.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-or-param-users.ll
@@ -1,9 +1,7 @@
 ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
 
-; CHECK-DAG: %[[#CHAR:]] = OpTypeInt 8
 ; CHECK-DAG: %[[#INT:]] = OpTypeInt 32
 ; CHECK-DAG: %[[#GLOBAL_PTR_INT:]] = OpTypePointer CrossWorkgroup %[[#INT]]
-; CHECK-DAG: %[[#GLOBAL_PTR_CHAR:]] = OpTypePointer CrossWorkgroup %[[#CHAR]]
 
 define i32 @foo(i32 %a, ptr addrspace(1) %p) {
   store i32 %a, i32 addrspace(1)* %p
@@ -12,8 +10,6 @@ define i32 @foo(i32 %a, ptr addrspace(1) %p) {
 }
 
 ; CHECK: %[[#A:]] = OpFunctionParameter %[[#INT]]
-; CHECK: %[[#P:]] = OpFunctionParameter %[[#GLOBAL_PTR_CHAR]]
-; CHECK: %[[#C:]] = OpBitcast %[[#GLOBAL_PTR_INT]] %[[#P]]
-; CHECK: OpStore %[[#C]] %[[#A]]
-; CHECK: %[[#B:]] = OpLoad %[[#INT]] %[[#C]]
-; CHECK-NOT: %[[#B:]] = OpLoad %[[#INT]] %[[#P]]
+; CHECK: %[[#CorP:]] = {{OpBitcast|OpFunctionParameter}}{{.*}}%[[#GLOBAL_PTR_INT]]{{.*}}
+; CHECK: OpStore %[[#CorP]] %[[#A]]
+; CHECK: %[[#B:]] = OpLoad %[[#INT]] %[[#CorP]]
diff --git a/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll b/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll
index 8998329ea64fe2..473c2a8b731115 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll
@@ -2,14 +2,13 @@
 
 ; CHECK-DAG: %[[#float:]] = OpTypeFloat 32
 ; CHECK-DAG: %[[#pointer:]] = OpTypePointer CrossWorkgroup %[[#float]]
-; CHECK: %[[#A:]] = OpFunctionParameter %[[#]]
 
 define void @foo(float addrspace(1)* %A, i32 %B) {
   %cmp = icmp sgt i32 %B, 0
   %conv = uitofp i1 %cmp to float
-; CHECK: %[[#utof_res:]] = OpConvertUToF %[[#float]] %[[#]]
-; CHECK: %[[#bitcast:]] = OpBitcast %[[#pointer]] %[[#A]]
-; CHECK: OpStore %[[#bitcast]] %[[#utof_res]]
+; CHECK-DAG: %[[#utof_res:]] = OpConvertUToF %[[#float]] %[[#]]
+; CHECK-DAG: %[[#bitcastORparam:]] = {{OpBitcast|OpFunctionParameter}}{{.*}}%[[#pointer]]{{.*}}
+; CHECK: OpStore %[[#bitcastORparam]] %[[#utof_res]]
   %BC1 = bitcast float addrspace(1)* %A to i32 addrspace(1)*
   %BC2 = bitcast i32 addrspace(1)* %BC1 to float addrspace(1)*
   store float %conv, float addrspace(1)* %BC2, align 4;
diff --git a/llvm/test/CodeGen/SPIRV/sitofp-with-bool.ll b/llvm/test/CodeGen/SPIRV/sitofp-with-bool.ll
index 06f27e2cb1f906..d9145e8d9f0a94 100644
--- a/llvm/test/CodeGen/SPIRV/sitofp-with-bool.ll
+++ b/llvm/test/CodeGen/SPIRV/sitofp-with-bool.ll
@@ -8,13 +8,12 @@
 ; CHECK-DAG: %[[#ptr:]] = OpTypePointer CrossWorkgroup %[[#float]]
 
 ; CHECK: OpFunction
-; CHECK: %[[#A:]] = OpFunctionParameter %[[#]]
+; CHECK: %[[#A:]] = OpFunctionParameter %[[#ptr]]
 ; CHECK: %[[#B:]] = OpFunctionParameter %[[#]]
 ; CHECK: %[[#cmp_res:]] = OpSGreaterThan %[[#bool]] %[[#B]] %[[#zero]]
 ; CHECK: %[[#select_res:]] = OpSelect %[[#int_32]] %[[#cmp_res]] %[[#one]] %[[#zero]]
 ; CHECK: %[[#stof_res:]] = OpConvertSToF %[[#]] %[[#select_res]]
-; CHECK: %[[#bitcast:]] = OpBitcast %[[#ptr]] %[[#A]]
-; CHECK: OpStore %[[#bitcast]] %[[#stof_res]]
+; CHECK: OpStore %[[#A]] %[[#stof_res]]
 
 define dso_local spir_kernel void @K(ptr addrspace(1) nocapture %A, i32 %B) local_unnamed_addr {
 entry:
diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll
index f4e6c83a8cd519..331960cdb341e7 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll
@@ -14,9 +14,8 @@
 ;; }
 
 ; CHECK-SPIRV:     OpName %[[#TEST:]] "test_atomic_cmpxchg"
-; CHECK-SPIRV-DAG: %[[#UCHAR:]] = OpTypeInt 8 0
 ; CHECK-SPIRV-DAG: %[[#UINT:]] = OpTypeInt 32 0
-; CHECK-SPIRV-DAG: %[[#UCHAR_PTR:]] = OpTypePointer CrossWorkgroup %[[#UCHAR]]
+; CHECK-SPIRV-DAG: %[[#UINT_PTR:]] = OpTypePointer CrossWorkgroup %[[#UINT]]
 
 ;; In SPIR-V, atomic_cmpxchg is represented as OpAtomicCompareExchange [2],
 ;; which also includes memory scope and two memory semantic arguments. The
@@ -31,7 +30,7 @@
 ; CHECK-SPIRV-DAG: %[[#RELAXED:]] = OpConstant %[[#UINT]] 0
 
 ; CHECK-SPIRV:     %[[#TEST]] = OpFunction %[[#]]
-; CHECK-SPIRV:     %[[#PTR:]] = OpFunctionParameter %[[#UCHAR_PTR]]
+; CHECK-SPIRV:     %[[#PTR:]] = OpFunctionParameter %[[#UINT_PTR]]
 ; CHECK-SPIRV:     %[[#CMP:]] = OpFunctionParameter %[[#UINT]]
 ; CHECK-SPIRV:     %[[#VAL:]] = OpFunctionParameter %[[#UINT]]
 ; CHECK-SPIRV:     %[[#]] = OpAtomicCompareExchange %[[#UINT]] %[[#PTR]] %[[#WORKGROUP_SCOPE]] %[[#RELAXED]] %[[#RELAXED]] %[[#VAL]] %[[#CMP]]
diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll
index 3e805e6eea97d0..95eb6ade11a25c 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll
@@ -11,8 +11,7 @@
 
 ; CHECK-SPIRV:     OpName %[[#TEST:]] "test_legacy_atomics"
 ; CHECK-SPIRV-DAG: %[[#UINT:]] = OpTypeInt 32 0
-; CHECK-SPIRV-DAG: %[[#UCHAR:]] = OpTypeInt 8 0
-; CHECK-SPIRV-DAG: %[[#UCHAR_PTR:]] = OpTypePointer CrossWorkgroup %[[#UCHAR]]
+; CHECK-SPIRV-DAG: %[[#UINT_PTR:]] = OpTypePointer CrossWorkgroup %[[#UINT]]
 
 ;; In SPIR-V, atomic_add is represented as OpAtomicIAdd [2], which also includes
 ;; memory scope and memory semantic arguments. The backend applies a default
@@ -26,7 +25,7 @@
 ; CHECK-SPIRV-DAG: %[[#RELAXED:]] = OpConstant %[[#UINT]] 0
 
 ; CHECK-SPIRV:     %[[#TEST]] = OpFunction %[[#]]
-; CHECK-SPIRV:     %[[#PTR:]] = OpFunctionParameter %[[#UCHAR_PTR]]
+; CHECK-SPIRV:     %[[#PTR:]] = OpFunctionParameter %[[#UINT_PTR]]
 ; CHECK-SPIRV:     %[[#VAL:]] = OpFunctionParameter %[[#UINT]]
 ; CHECK-SPIRV:     %[[#]] = OpAtomicIAdd %[[#UINT]] %[[#PTR]] %[[#WORKGROUP_SCOPE]] %[[#RELAXED]] %[[#VAL]]
 ; CHECK-SPIRV:     %[[#]] = OpAtomicIAdd %[[#UINT]] %[[#PTR]] %[[#WORKGROUP_SCOPE]] %[[#RELAXED]] %[[#VAL]]
diff --git a/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll b/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll
index a07af76c223240..3551030843d062 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll
@@ -13,7 +13,6 @@
 ; CHECK-SPIRV:     %[[#test_arr2:]] = OpVariable %[[#const_i32x3_ptr]] UniformConstant %[[#test_arr_init]]
 ; CHECK-SPIRV:     %[[#test_arr:]] = OpVariable %[[#const_i32x3_ptr]] UniformConstant %[[#test_arr_init]]
 
-; CHECK-SPIRV-DAG: %[[#i8_ptr:]] = OpTypePointer Function %[[#i8]]
 ; CHECK-SPIRV-DAG: %[[#const_i8_ptr:]] = OpTypePointer UniformConstant %[[#i8]]
 ; CHECK-SPIRV-DAG: %[[#i32x3_ptr:]] = OpTypePointer Function %[[#i32x3]]
 
diff --git a/llvm/test/CodeGen/SPIRV/uitofp-with-bool.ll b/llvm/test/CodeGen/SPIRV/uitofp-with-bool.ll
index 8a3c2853d99149..6f793fc5d030e6 100644
--- a/llvm/test/CodeGen/SPIRV/uitofp-with-bool.ll
+++ b/llvm/test/CodeGen/SPIRV/uitofp-with-bool.ll
@@ -69,7 +69,7 @@
 ; SPV-DAG: %[[#pointer:]] = OpTypePointer CrossWorkgroup %[[#float]]
 
 ; SPV-DAG: OpFunction
-; SPV-DAG: %[[#A:]] = OpFunctionParameter %[[#]]
+; SPV-DAG: %[[#A:]] = OpFunctionParameter %[[#pointer]]
 ; SPV-DAG: %[[#B:]] = OpFunctionParameter %[[#]]
 ; SPV-DAG: %[[#i1s:]] = OpFunctionParameter %[[#]]
 ; SPV-DAG: %[[#i1v:]] = OpFunctionParameter %[[#]]
@@ -82,8 +82,7 @@ entry:
 ; SPV-DAG: %[[#select_res:]] = OpSelect %[[#int_32]] %[[#cmp_res]] %[[#one_32]] %[[#zero_32]]
 ; SPV-DAG: %[[#utof_res:]] = OpConvertUToF %[[#float]] %[[#select_res]]
   %conv = uitofp i1 %cmp to float
-; SPV-DAG: %[[#bitcast:]] = OpBitcast %[[#pointer]] %[[#A]]
-; SPV-DAG: OpStore %[[#bitcast]] %[[#utof_res]]
+; SPV-DAG: OpStore %[[#A]] %[[#utof_res]]
   store float %conv, float addrspace(1)* %A, align 4;
 
 ; SPV-DAG: %[[#s1]] = OpSelect %[[#int_8]] %[[#i1s]] %[[#mone_8]] %[[#zero_8]]



More information about the llvm-commits mailing list