diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMIRFormatter.h b/llvm/lib/Target/AMDGPU/AMDGPUMIRFormatter.h
new file mode 100644
--- /dev/null
+++ b/llvm/lib/Target/AMDGPU/AMDGPUMIRFormatter.h
@@ -0,0 +1,47 @@
+//===-- llvm/Target/AMDGPU/AMDGPUMIRFormatter.h -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// AMDGPU specific overrides of MIRFormatter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_AMDGPUMIRFORMATTER_H
+#define LLVM_LIB_TARGET_AMDGPUMIRFORMATTER_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/CodeGen/MIRFormatter.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+
+namespace llvm {
+
+class MachineFunction;
+class MachineInstr;
+struct PerFunctionMIParsingState;
+struct SlotMapping;
+
+class AMDGPUMIRFormatter final : public MIRFormatter {
+public:
+  AMDGPUMIRFormatter() {}
+  virtual ~AMDGPUMIRFormatter() = default;
+
+  /// Implement target specific parsing of target custom pseudo source value.
+  virtual bool
+  parseCustomPseudoSourceValue(StringRef Src, MachineFunction &MF,
+                               PerFunctionMIParsingState &PFS,
+                               const PseudoSourceValue *&PSV,
+                               ErrorCallbackType ErrorCallback) const override;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMIRFormatter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUMIRFormatter.cpp
new file mode 100644
--- /dev/null
+++ b/llvm/lib/Target/AMDGPU/AMDGPUMIRFormatter.cpp
@@ -0,0 +1,38 @@
+//===- AMDGPUMIRFormatter.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Implementation of AMDGPU overrides of MIRFormatter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AMDGPUMIRFormatter.h"
+#include "SIMachineFunctionInfo.h"
+
+using namespace llvm;
+
+bool AMDGPUMIRFormatter::parseCustomPseudoSourceValue(
+    StringRef Src, MachineFunction &MF, PerFunctionMIParsingState &PFS,
+    const PseudoSourceValue *&PSV, ErrorCallbackType ErrorCallback) const {
+  if (Src == "TargetCustom7") {
+    const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
+    PSV = new AMDGPUBufferPseudoSourceValue(*TII);
+    return false;
+  }
+  if (Src == "TargetCustom8") {
+    const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
+    PSV = new AMDGPUImagePseudoSourceValue(*TII);
+    return false;
+  }
+  if (Src == "TargetCustom9") {
+    const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
+    PSV = new AMDGPUGWSResourcePseudoSourceValue(*TII);
+    return false;
+  }
+  llvm_unreachable("unknown MIR custom pseudo source value");
+}
diff --git a/llvm/lib/Target/AMDGPU/CMakeLists.txt b/llvm/lib/Target/AMDGPU/CMakeLists.txt
--- a/llvm/lib/Target/AMDGPU/CMakeLists.txt
+++ b/llvm/lib/Target/AMDGPU/CMakeLists.txt
@@ -72,6 +72,7 @@
   AMDGPUMachineModuleInfo.cpp
   AMDGPUMacroFusion.cpp
   AMDGPUMCInstLower.cpp
+  AMDGPUMIRFormatter.cpp
   AMDGPUOpenCLEnqueuedBlockLowering.cpp
   AMDGPUPostLegalizerCombiner.cpp
   AMDGPUPreLegalizerCombiner.cpp
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.h b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
 #define LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
 
+#include "AMDGPUMIRFormatter.h"
 #include "SIRegisterInfo.h"
 #include "Utils/AMDGPUBaseInfo.h"
 #include "llvm/ADT/SetVector.h"
@@ -39,6 +40,7 @@
   const SIRegisterInfo RI;
   const GCNSubtarget &ST;
   TargetSchedModel SchedModel;
+  mutable std::unique_ptr<AMDGPUMIRFormatter> Formatter;
 
   // The inverse predicate should have the negative value.
   enum BranchPredicate {
@@ -1076,6 +1078,12 @@
                            const MachineInstr &MI,
                            unsigned *PredCost = nullptr) const override;
 
+  const MIRFormatter *getMIRFormatter() const override {
+    if (!Formatter.get())
+      Formatter = std::make_unique<AMDGPUMIRFormatter>();
+    return Formatter.get();
+  }
+
   static unsigned getDSShaderTypeValue(const MachineFunction &MF);
 };
 
diff --git a/llvm/test/CodeGen/AMDGPU/custom-addrspace.mir b/llvm/test/CodeGen/AMDGPU/custom-addrspace.mir
new file mode 100644
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/custom-addrspace.mir
@@ -0,0 +1,34 @@
+# RUN: llc -march=amdgcn -mcpu=gfx1010 -verify-machineinstrs -run-pass si-wqm -o -  %s | FileCheck %s
+
+---
+# Test that compilation does not fail.
+#CHECK-LABEL: name: addrspaces
+#CHECK: %5:vreg_64 = BUFFER_LOAD_DWORDX2_OFFSET %3, 0, 8, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 8 from custom "TargetCustom7" + 8, align 1, addrspace 4)
+#CHECK-NEXT: %6:vreg_128 = IMPLICIT_DEF
+#CHECK-NEXT: %6.sub0:vreg_128 = COPY %5.sub0
+#CHECK-NEXT: IMAGE_STORE_V4_V3_nsa_gfx10 %6, %0, %1, %4, %2, 15, 2, -1, 0, 0, 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom "TargetCustom8")
+name:            addrspaces
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $sgpr1, $sgpr2, $vgpr1, $vgpr2
+
+    $m0 = COPY $sgpr1
+    %0:vgpr_32 = COPY $vgpr1
+    %1:vgpr_32 = COPY $vgpr2
+    %100:sgpr_256 = IMPLICIT_DEF
+    %101:sgpr_128 = IMPLICIT_DEF
+
+    %2:vgpr_32 = V_INTERP_P1_F32 %0:vgpr_32, 3, 2, implicit $mode, implicit $m0, implicit $exec
+
+    %5:vreg_64 = BUFFER_LOAD_DWORDX2_OFFSET %101, 0, 8, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 8 from custom "TargetCustom7" + 8, align 1, addrspace 4)
+    %6:vreg_128 = IMPLICIT_DEF
+    %6.sub0:vreg_128 = COPY killed %5.sub0
+    IMAGE_STORE_V4_V3_nsa_gfx10 %6, %0, %1, %2, %100, 15, 2, -1, 0, 0, 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom "TargetCustom8")
+
+    $vgpr0 = COPY %6.sub0:vreg_128
+    $vgpr1 = COPY %6.sub1:vreg_128
+    $vgpr2 = COPY %6.sub2:vreg_128
+    $vgpr3 = COPY %6.sub3:vreg_128
+    SI_RETURN_TO_EPILOG $vgpr0, $vgpr1, $vgpr2, $vgpr3
+...