[llvm] 698dd11 - AMDGPU: Use the addrspacecast nonnull flag in codegen (#220926)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 8 02:14:08 PDT 2026


Author: Matt Arsenault
Date: 2026-09-08T11:14:02+02:00
New Revision: 698dd11893fca65681f8cd84b39ff49d29ddcd1e

URL: https://github.com/llvm/llvm-project/commit/698dd11893fca65681f8cd84b39ff49d29ddcd1e
DIFF: https://github.com/llvm/llvm-project/commit/698dd11893fca65681f8cd84b39ff49d29ddcd1e.diff

LOG: AMDGPU: Use the addrspacecast nonnull flag in codegen (#220926)

Plumb the nonnull flag through to the backend so a flagged addrspacecast
lowers without the runtime null check, matching what
llvm.amdgcn.addrspacecast.nonnull already provides.

Add the NonNull MIFlag with MIR printer/parser support (including the
MIRPrinter path and update_mir_test_checks) so it round-trips on
G_ADDRSPACE_CAST, and preserve it through SelectionDAG vector
scalarization and splitting.

Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>

Added: 
    llvm/test/CodeGen/AMDGPU/addrspacecast-nonnull.ll
    llvm/test/CodeGen/MIR/AMDGPU/addrspacecast-nonnull.mir

Modified: 
    llvm/include/llvm/CodeGen/MachineInstr.h
    llvm/include/llvm/CodeGen/SelectionDAG.h
    llvm/include/llvm/CodeGen/SelectionDAGNodes.h
    llvm/lib/CodeGen/MIRParser/MILexer.cpp
    llvm/lib/CodeGen/MIRParser/MILexer.h
    llvm/lib/CodeGen/MIRParser/MIParser.cpp
    llvm/lib/CodeGen/MIRPrinter.cpp
    llvm/lib/CodeGen/MachineInstr.cpp
    llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
    llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
    llvm/lib/Target/AMDGPU/SIISelLowering.cpp
    llvm/utils/UpdateTestChecks/mir.py

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index b04018e43bbe0..87e40501b3f3c 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -128,7 +128,9 @@ class MachineInstr
     SameSign = 1 << 21,      // Both operands have the same sign.
     InBounds = 1 << 22,      // Pointer arithmetic remains inbounds.
                              // Implies NoUSWrap.
-    LRSplit = 1 << 23        // Instruction for live range split.
+    LRSplit = 1 << 23,       // Instruction for live range split.
+    NonNull = 1 << 24        // Address space cast source is not the null
+                             // value of the source address space.
   };
 
 private:

diff  --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index c1acf6aaf5b6f..b00fdb2ef05c5 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -1746,7 +1746,8 @@ class SelectionDAG {
 
   /// Return an AddrSpaceCastSDNode.
   LLVM_ABI SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr,
-                                    unsigned SrcAS, unsigned DestAS);
+                                    unsigned SrcAS, unsigned DestAS,
+                                    const SDNodeFlags Flags = SDNodeFlags());
 
   /// Return a freeze using the SDLoc of the value operand.
   LLVM_ABI SDValue getFreeze(SDValue V);

diff  --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 0fa4385c53bcc..667c98f086827 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -424,13 +424,17 @@ struct SDNodeFlags {
     // Call does not require convergence guarantees.
     NoConvergent = 1 << 16,
 
+    // ISD::ADDRSPACECAST where the source is known not to be the null value of
+    // the source address space, so the result is poison if the source is null.
+    NonNull = 1 << 17,
+
     // NOTE: Please update LargestValue in LLVM_DECLARE_ENUM_AS_BITMASK below
     // the class definition when adding new flags.
 
     PoisonGeneratingFlags = NoUnsignedWrap | NoSignedWrap | Exact | Disjoint |
-                            NonNeg | NoNaNs | NoInfs | SameSign | InBounds,
+        NonNeg | NoNaNs | NoInfs | SameSign | InBounds | NonNull,
     FastMathFlags = NoNaNs | NoInfs | NoSignedZeros | AllowReciprocal |
-                    AllowContract | ApproximateFuncs | AllowReassociation,
+        AllowContract | ApproximateFuncs | AllowReassociation,
   };
 
   /// Default constructor turns off all optimization flags.
@@ -465,6 +469,7 @@ struct SDNodeFlags {
   void setUnpredictable(bool b) { setFlag<Unpredictable>(b); }
   void setInBounds(bool b) { setFlag<InBounds>(b); }
   void setNoConvergent(bool b) { setFlag<NoConvergent>(b); }
+  void setNonNull(bool b) { setFlag<NonNull>(b); }
 
   // These are accessors for each flag.
   bool hasNoUnsignedWrap() const { return Flags & NoUnsignedWrap; }
@@ -484,6 +489,7 @@ struct SDNodeFlags {
   bool hasUnpredictable() const { return Flags & Unpredictable; }
   bool hasInBounds() const { return Flags & InBounds; }
   bool hasNoConvergent() const { return Flags & NoConvergent; }
+  bool hasNonNull() const { return Flags & NonNull; }
 
   bool operator==(const SDNodeFlags &Other) const {
     return Flags == Other.Flags;
@@ -492,8 +498,7 @@ struct SDNodeFlags {
   void operator|=(const SDNodeFlags &OtherFlags) { Flags |= OtherFlags.Flags; }
 };
 
-LLVM_DECLARE_ENUM_AS_BITMASK(decltype(SDNodeFlags::None),
-                             SDNodeFlags::NoConvergent);
+LLVM_DECLARE_ENUM_AS_BITMASK(decltype(SDNodeFlags::None), SDNodeFlags::NonNull);
 
 inline SDNodeFlags operator|(SDNodeFlags LHS, SDNodeFlags RHS) {
   LHS |= RHS;

diff  --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
index 67fbc00edd9db..0851c42c7777f 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
@@ -218,6 +218,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
       .Case("disjoint", MIToken::kw_disjoint)
       .Case("samesign", MIToken::kw_samesign)
       .Case("inbounds", MIToken::kw_inbounds)
+      .Case("nonnull", MIToken::kw_nonnull)
       .Case("nofpexcept", MIToken::kw_nofpexcept)
       .Case("unpredictable", MIToken::kw_unpredictable)
       .Case("debug-location", MIToken::kw_debug_location)

diff  --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h
index f5947bfe59b9d..0e28ee3635a87 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.h
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.h
@@ -79,6 +79,7 @@ struct MIToken {
     kw_disjoint,
     kw_samesign,
     kw_inbounds,
+    kw_nonnull,
     kw_debug_location,
     kw_debug_instr_number,
     kw_dbg_instr_ref,

diff  --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index ef4927e2c4ee3..4b951785e9c41 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1389,6 +1389,7 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) {
          Token.is(MIToken::kw_nusw) ||
          Token.is(MIToken::kw_samesign) ||
          Token.is(MIToken::kw_inbounds) ||
+         Token.is(MIToken::kw_nonnull) ||
          Token.is(MIToken::kw_lr_split)) {
     // clang-format on
     // Mine frame and fast math flags
@@ -1432,6 +1433,8 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) {
       Flags |= MachineInstr::SameSign;
     if (Token.is(MIToken::kw_inbounds))
       Flags |= MachineInstr::InBounds;
+    if (Token.is(MIToken::kw_nonnull))
+      Flags |= MachineInstr::NonNull;
     if (Token.is(MIToken::kw_lr_split))
       Flags |= MachineInstr::LRSplit;
 

diff  --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index 8acd6f14ebc2e..5a4aa4910c0d3 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -894,6 +894,8 @@ static void printMI(raw_ostream &OS, MFPrintState &State,
     OS << "inbounds ";
   if (MI.getFlag(MachineInstr::LRSplit))
     OS << "lr-split ";
+  if (MI.getFlag(MachineInstr::NonNull))
+    OS << "nonnull ";
 
   // NOTE: Please add new MIFlags also to the MI_FLAGS_STR in
   // llvm/utils/UpdateTestChecks/mir.py.

diff  --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index a3dce5513deef..3ed2ea5e20dc6 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -621,6 +621,11 @@ uint32_t MachineInstr::copyFlagsFromInstruction(const Instruction &I) {
     if (ICmp->hasSameSign())
       MIFlags |= MachineInstr::MIFlag::SameSign;
 
+  // Copy the nonnull flag.
+  if (const auto *ASC = dyn_cast<AddrSpaceCastInst>(&I))
+    if (ASC->hasNonNull())
+      MIFlags |= MachineInstr::MIFlag::NonNull;
+
   // Copy the exact flag.
   if (const PossiblyExactOperator *PE = dyn_cast<PossiblyExactOperator>(&I))
     if (PE->isExact())
@@ -1899,6 +1904,8 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
     OS << "inbounds ";
   if (getFlag(MachineInstr::LRSplit))
     OS << "lr-split ";
+  if (getFlag(MachineInstr::NonNull))
+    OS << "nonnull ";
 
   // Print the opcode name.
   if (TII)

diff  --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 0215f8f5e00c0..e997e350deb92 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -663,7 +663,8 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_ADDRSPACECAST(SDNode *N) {
   auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
   unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
   unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
-  return DAG.getAddrSpaceCast(DL, DestVT, Op, SrcAS, DestAS);
+  return DAG.getAddrSpaceCast(DL, DestVT, Op, SrcAS, DestAS,
+                              AddrSpaceCastN->getFlags());
 }
 
 SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
@@ -2991,8 +2992,9 @@ void DAGTypeLegalizer::SplitVecRes_ADDRSPACECAST(SDNode *N, SDValue &Lo,
   auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
   unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
   unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
-  Lo = DAG.getAddrSpaceCast(dl, LoVT, Lo, SrcAS, DestAS);
-  Hi = DAG.getAddrSpaceCast(dl, HiVT, Hi, SrcAS, DestAS);
+  SDNodeFlags Flags = AddrSpaceCastN->getFlags();
+  Lo = DAG.getAddrSpaceCast(dl, LoVT, Lo, SrcAS, DestAS, Flags);
+  Hi = DAG.getAddrSpaceCast(dl, HiVT, Hi, SrcAS, DestAS, Flags);
 }
 
 void DAGTypeLegalizer::SplitVecRes_UnaryOpWithTwoResults(SDNode *N,
@@ -6325,9 +6327,9 @@ SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
     InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(InWidenVT), InOp, 0);
   }
 
-  return DAG.getAddrSpaceCast(DL, WidenVT, InOp,
-                              AddrSpaceCastN->getSrcAddressSpace(),
-                              AddrSpaceCastN->getDestAddressSpace());
+  return DAG.getAddrSpaceCast(
+      DL, WidenVT, InOp, AddrSpaceCastN->getSrcAddressSpace(),
+      AddrSpaceCastN->getDestAddressSpace(), AddrSpaceCastN->getFlags());
 }
 
 SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 94686c2a65ff3..eadbe60742f3e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2500,7 +2500,8 @@ SDValue SelectionDAG::getBitcast(EVT VT, SDValue V) {
 }
 
 SDValue SelectionDAG::getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr,
-                                       unsigned SrcAS, unsigned DestAS) {
+                                       unsigned SrcAS, unsigned DestAS,
+                                       const SDNodeFlags Flags) {
   SDVTList VTs = getVTList(VT);
   SDValue Ops[] = {Ptr};
   SDNodeKey ID(ISD::ADDRSPACECAST, VTs, Ops);
@@ -2508,11 +2509,14 @@ SDValue SelectionDAG::getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr,
   ID.AddInteger(DestAS);
 
   FoldingSetInsertToken InsertToken;
-  if (SDNode *E = lookupNode(ID, dl, InsertToken))
+  if (SDNode *E = lookupNode(ID, dl, InsertToken)) {
+    E->intersectFlagsWith(Flags);
     return SDValue(E, 0);
+  }
 
   auto *N = newSDNode<AddrSpaceCastSDNode>(dl.getIROrder(), dl.getDebugLoc(),
                                            VTs, SrcAS, DestAS);
+  N->setFlags(Flags);
   createOperands(N, Ops);
 
   CSEMap.insert(N, InsertToken);
@@ -14349,9 +14353,9 @@ SDValue SelectionDAG::UnrollVectorOp(SDNode *N, unsigned ResNE) {
     }
     case ISD::ADDRSPACECAST: {
       const auto *ASC = cast<AddrSpaceCastSDNode>(N);
-      Scalars.push_back(getAddrSpaceCast(dl, EltVT, Operands[0],
-                                         ASC->getSrcAddressSpace(),
-                                         ASC->getDestAddressSpace()));
+      Scalars.push_back(
+          getAddrSpaceCast(dl, EltVT, Operands[0], ASC->getSrcAddressSpace(),
+                           ASC->getDestAddressSpace(), ASC->getFlags()));
       break;
     }
     }

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index f34f1c7e9c969..794a4e6e1b537 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4176,8 +4176,12 @@ void SelectionDAGBuilder::visitAddrSpaceCast(const User &I) {
   unsigned SrcAS = SV->getType()->getPointerAddressSpace();
   unsigned DestAS = I.getType()->getPointerAddressSpace();
 
-  if (!TM.isNoopAddrSpaceCast(SrcAS, DestAS))
-    N = DAG.getAddrSpaceCast(getCurSDLoc(), DestVT, N, SrcAS, DestAS);
+  if (!TM.isNoopAddrSpaceCast(SrcAS, DestAS)) {
+    SDNodeFlags Flags;
+    if (const auto *ASC = dyn_cast<AddrSpaceCastInst>(&I))
+      Flags.setNonNull(ASC->hasNonNull());
+    N = DAG.getAddrSpaceCast(getCurSDLoc(), DestVT, N, SrcAS, DestAS, Flags);
+  }
 
   setValue(&I, N);
 }

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index c6a8fe568064d..32e0cafd9f71c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -740,6 +740,9 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
   if (getFlags().hasNonNeg())
     OS << " nneg";
 
+  if (getFlags().hasNonNull())
+    OS << " nonnull";
+
   if (getFlags().hasNoNaNs())
     OS << " nnan";
 

diff  --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index faa0d3994fcd0..c4a7c77f6968f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -2556,6 +2556,11 @@ bool AMDGPULegalizerInfo::legalizeAddrSpaceCast(
   const AMDGPUTargetMachine &TM
     = static_cast<const AMDGPUTargetMachine &>(MF.getTarget());
 
+  // The source is known non-null for llvm.amdgcn.addrspacecast.nonnull or a
+  // G_ADDRSPACE_CAST carrying the nonnull flag; otherwise we need to guess.
+  const bool IsNonNull =
+      isa<GIntrinsic>(MI) || MI.getFlag(MachineInstr::MIFlag::NonNull);
+
   if (TM.isNoopAddrSpaceCast(SrcAS, DestAS)) {
     MI.setDesc(B.getTII().get(TargetOpcode::G_BITCAST));
     return true;
@@ -2583,9 +2588,7 @@ bool AMDGPULegalizerInfo::legalizeAddrSpaceCast(
       return B.buildExtract(Dst, Src, 0).getReg(0);
     };
 
-    // For llvm.amdgcn.addrspacecast.nonnull we can always assume non-null, for
-    // G_ADDRSPACE_CAST we need to guess.
-    if (isa<GIntrinsic>(MI) || isKnownNonNull(Src, MRI, TM, SrcAS)) {
+    if (IsNonNull || isKnownNonNull(Src, MRI, TM, SrcAS)) {
       castFlatToLocalOrPrivate(Dst);
       MI.eraseFromParent();
       return true;
@@ -2655,9 +2658,7 @@ bool AMDGPULegalizerInfo::legalizeAddrSpaceCast(
       return B.buildMergeLikeInstr(Dst, {SrcAsInt, ApertureReg}).getReg(0);
     };
 
-    // For llvm.amdgcn.addrspacecast.nonnull we can always assume non-null, for
-    // G_ADDRSPACE_CAST we need to guess.
-    if (isa<GIntrinsic>(MI) || isKnownNonNull(Src, MRI, TM, SrcAS)) {
+    if (IsNonNull || isKnownNonNull(Src, MRI, TM, SrcAS)) {
       castLocalOrPrivateToFlat(Dst);
       MI.eraseFromParent();
       return true;

diff  --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 1ec23da794bca..3bad6d330c0ad 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -9419,6 +9419,7 @@ SDValue SITargetLowering::lowerADDRSPACECAST(SDValue Op,
     SrcAS = ASC->getSrcAddressSpace();
     Src = ASC->getOperand(0);
     DestAS = ASC->getDestAddressSpace();
+    IsNonNull = ASC->getFlags().hasNonNull();
   } else {
     assert(Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN &&
            Op.getConstantOperandVal(0) ==

diff  --git a/llvm/test/CodeGen/AMDGPU/addrspacecast-nonnull.ll b/llvm/test/CodeGen/AMDGPU/addrspacecast-nonnull.ll
new file mode 100644
index 0000000000000..afefa784fabbb
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/addrspacecast-nonnull.ll
@@ -0,0 +1,299 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc -global-isel=0 -mtriple=amdgpu9.00-amd-amdhsa < %s | FileCheck --check-prefixes=CHECK,DAGISEL %s
+; RUN: llc -global-isel=1 -mtriple=amdgpu9.00-amd-amdhsa < %s | FileCheck --check-prefixes=CHECK,GISEL %s
+
+; The nonnull flag on addrspacecast allows the target to skip the null check
+; that maps a source null pointer to the destination null pointer.
+
+define void @local_to_flat(ptr addrspace(3) %ptr) {
+; CHECK-LABEL: local_to_flat:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT:    s_mov_b64 s[4:5], src_shared_base
+; CHECK-NEXT:    v_mov_b32_e32 v1, s5
+; CHECK-NEXT:    v_mov_b32_e32 v2, 7
+; CHECK-NEXT:    flat_store_dword v[0:1], v2
+; CHECK-NEXT:    s_waitcnt vmcnt(0) lgkmcnt(0)
+; CHECK-NEXT:    s_setpc_b64 s[30:31]
+  %1 = addrspacecast nonnull ptr addrspace(3) %ptr to ptr
+  store volatile i32 7, ptr %1, align 4
+  ret void
+}
+
+define void @private_to_flat(ptr addrspace(5) %ptr) {
+; CHECK-LABEL: private_to_flat:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT:    s_mov_b64 s[4:5], src_private_base
+; CHECK-NEXT:    v_mov_b32_e32 v1, s5
+; CHECK-NEXT:    v_mov_b32_e32 v2, 7
+; CHECK-NEXT:    flat_store_dword v[0:1], v2
+; CHECK-NEXT:    s_waitcnt vmcnt(0) lgkmcnt(0)
+; CHECK-NEXT:    s_setpc_b64 s[30:31]
+  %1 = addrspacecast nonnull ptr addrspace(5) %ptr to ptr
+  store volatile i32 7, ptr %1, align 4
+  ret void
+}
+
+define void @flat_to_local(ptr %ptr) {
+; CHECK-LABEL: flat_to_local:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT:    v_mov_b32_e32 v1, 7
+; CHECK-NEXT:    ds_write_b32 v0, v1
+; CHECK-NEXT:    s_waitcnt lgkmcnt(0)
+; CHECK-NEXT:    s_setpc_b64 s[30:31]
+  %1 = addrspacecast nonnull ptr %ptr to ptr addrspace(3)
+  store volatile i32 7, ptr addrspace(3) %1, align 4
+  ret void
+}
+
+define void @flat_to_private(ptr %ptr) {
+; CHECK-LABEL: flat_to_private:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT:    v_mov_b32_e32 v1, 7
+; CHECK-NEXT:    buffer_store_dword v1, v0, s[0:3], 0 offen
+; CHECK-NEXT:    s_waitcnt vmcnt(0)
+; CHECK-NEXT:    s_setpc_b64 s[30:31]
+  %1 = addrspacecast nonnull ptr %ptr to ptr addrspace(5)
+  store volatile i32 7, ptr addrspace(5) %1, align 4
+  ret void
+}
+
+; The nonnull flag must survive scalarization of a vector addrspacecast, so no
+; per-element null check is emitted.
+define <2 x ptr> @local_to_flat_vector(<2 x ptr addrspace(3)> %ptr) {
+; CHECK-LABEL: local_to_flat_vector:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT:    s_mov_b64 s[4:5], src_shared_base
+; CHECK-NEXT:    v_mov_b32_e32 v2, v1
+; CHECK-NEXT:    v_mov_b32_e32 v1, s5
+; CHECK-NEXT:    v_mov_b32_e32 v3, s5
+; CHECK-NEXT:    s_setpc_b64 s[30:31]
+  %1 = addrspacecast nonnull <2 x ptr addrspace(3)> %ptr to <2 x ptr>
+  ret <2 x ptr> %1
+}
+
+; The nonnull flag must also survive vector type-legalization that splits the
+; addrspacecast (v32 splits repeatedly).
+define <32 x ptr> @local_to_flat_vector_split(<32 x ptr addrspace(3)> %ptr) {
+; DAGISEL-LABEL: local_to_flat_vector_split:
+; DAGISEL:       ; %bb.0:
+; DAGISEL-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; DAGISEL-NEXT:    buffer_store_dword v30, v0, s[0:3], 0 offen offset:232
+; DAGISEL-NEXT:    buffer_store_dword v29, v0, s[0:3], 0 offen offset:224
+; DAGISEL-NEXT:    buffer_store_dword v28, v0, s[0:3], 0 offen offset:216
+; DAGISEL-NEXT:    buffer_store_dword v27, v0, s[0:3], 0 offen offset:208
+; DAGISEL-NEXT:    buffer_store_dword v26, v0, s[0:3], 0 offen offset:200
+; DAGISEL-NEXT:    buffer_load_dword v26, off, s[0:3], s32 offset:4
+; DAGISEL-NEXT:    s_nop 0
+; DAGISEL-NEXT:    buffer_load_dword v27, off, s[0:3], s32
+; DAGISEL-NEXT:    s_mov_b64 s[4:5], src_shared_base
+; DAGISEL-NEXT:    buffer_store_dword v25, v0, s[0:3], 0 offen offset:192
+; DAGISEL-NEXT:    buffer_store_dword v24, v0, s[0:3], 0 offen offset:184
+; DAGISEL-NEXT:    buffer_store_dword v23, v0, s[0:3], 0 offen offset:176
+; DAGISEL-NEXT:    buffer_store_dword v22, v0, s[0:3], 0 offen offset:168
+; DAGISEL-NEXT:    buffer_store_dword v21, v0, s[0:3], 0 offen offset:160
+; DAGISEL-NEXT:    buffer_store_dword v20, v0, s[0:3], 0 offen offset:152
+; DAGISEL-NEXT:    buffer_store_dword v19, v0, s[0:3], 0 offen offset:144
+; DAGISEL-NEXT:    buffer_store_dword v18, v0, s[0:3], 0 offen offset:136
+; DAGISEL-NEXT:    buffer_store_dword v17, v0, s[0:3], 0 offen offset:128
+; DAGISEL-NEXT:    buffer_store_dword v16, v0, s[0:3], 0 offen offset:120
+; DAGISEL-NEXT:    buffer_store_dword v15, v0, s[0:3], 0 offen offset:112
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:104
+; DAGISEL-NEXT:    v_mov_b32_e32 v14, s5
+; DAGISEL-NEXT:    buffer_store_dword v13, v0, s[0:3], 0 offen offset:96
+; DAGISEL-NEXT:    buffer_store_dword v12, v0, s[0:3], 0 offen offset:88
+; DAGISEL-NEXT:    buffer_store_dword v11, v0, s[0:3], 0 offen offset:80
+; DAGISEL-NEXT:    buffer_store_dword v10, v0, s[0:3], 0 offen offset:72
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:252
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:244
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:236
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:228
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:220
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:212
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:204
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:196
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:188
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:180
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:172
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:164
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:156
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:148
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:140
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:132
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:124
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:116
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:108
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:100
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:92
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:84
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:76
+; DAGISEL-NEXT:    s_waitcnt vmcnt(40)
+; DAGISEL-NEXT:    buffer_store_dword v26, v0, s[0:3], 0 offen offset:248
+; DAGISEL-NEXT:    s_waitcnt vmcnt(40)
+; DAGISEL-NEXT:    buffer_store_dword v27, v0, s[0:3], 0 offen offset:240
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:68
+; DAGISEL-NEXT:    buffer_store_dword v9, v0, s[0:3], 0 offen offset:64
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:60
+; DAGISEL-NEXT:    buffer_store_dword v8, v0, s[0:3], 0 offen offset:56
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:52
+; DAGISEL-NEXT:    buffer_store_dword v7, v0, s[0:3], 0 offen offset:48
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:44
+; DAGISEL-NEXT:    buffer_store_dword v6, v0, s[0:3], 0 offen offset:40
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:36
+; DAGISEL-NEXT:    buffer_store_dword v5, v0, s[0:3], 0 offen offset:32
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:28
+; DAGISEL-NEXT:    buffer_store_dword v4, v0, s[0:3], 0 offen offset:24
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:20
+; DAGISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:16
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:12
+; DAGISEL-NEXT:    buffer_store_dword v2, v0, s[0:3], 0 offen offset:8
+; DAGISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:4
+; DAGISEL-NEXT:    buffer_store_dword v1, v0, s[0:3], 0 offen
+; DAGISEL-NEXT:    s_waitcnt vmcnt(0)
+; DAGISEL-NEXT:    s_setpc_b64 s[30:31]
+;
+; GISEL-LABEL: local_to_flat_vector_split:
+; GISEL:       ; %bb.0:
+; GISEL-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GISEL-NEXT:    buffer_store_dword v1, v0, s[0:3], 0 offen
+; GISEL-NEXT:    buffer_store_dword v2, v0, s[0:3], 0 offen offset:8
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:16
+; GISEL-NEXT:    buffer_store_dword v4, v0, s[0:3], 0 offen offset:24
+; GISEL-NEXT:    buffer_load_dword v1, off, s[0:3], s32
+; GISEL-NEXT:    s_mov_b64 s[4:5], src_shared_base
+; GISEL-NEXT:    buffer_load_dword v2, off, s[0:3], s32 offset:4
+; GISEL-NEXT:    v_mov_b32_e32 v3, s5
+; GISEL-NEXT:    buffer_store_dword v5, v0, s[0:3], 0 offen offset:32
+; GISEL-NEXT:    buffer_store_dword v6, v0, s[0:3], 0 offen offset:40
+; GISEL-NEXT:    buffer_store_dword v7, v0, s[0:3], 0 offen offset:48
+; GISEL-NEXT:    buffer_store_dword v8, v0, s[0:3], 0 offen offset:56
+; GISEL-NEXT:    buffer_store_dword v9, v0, s[0:3], 0 offen offset:64
+; GISEL-NEXT:    buffer_store_dword v10, v0, s[0:3], 0 offen offset:72
+; GISEL-NEXT:    buffer_store_dword v11, v0, s[0:3], 0 offen offset:80
+; GISEL-NEXT:    buffer_store_dword v12, v0, s[0:3], 0 offen offset:88
+; GISEL-NEXT:    buffer_store_dword v13, v0, s[0:3], 0 offen offset:96
+; GISEL-NEXT:    buffer_store_dword v14, v0, s[0:3], 0 offen offset:104
+; GISEL-NEXT:    buffer_store_dword v15, v0, s[0:3], 0 offen offset:112
+; GISEL-NEXT:    buffer_store_dword v16, v0, s[0:3], 0 offen offset:120
+; GISEL-NEXT:    buffer_store_dword v17, v0, s[0:3], 0 offen offset:128
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:4
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:12
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:20
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:28
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:36
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:44
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:52
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:60
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:68
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:76
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:84
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:92
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:100
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:108
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:116
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:124
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:132
+; GISEL-NEXT:    buffer_store_dword v18, v0, s[0:3], 0 offen offset:136
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:140
+; GISEL-NEXT:    buffer_store_dword v19, v0, s[0:3], 0 offen offset:144
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:148
+; GISEL-NEXT:    buffer_store_dword v20, v0, s[0:3], 0 offen offset:152
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:156
+; GISEL-NEXT:    buffer_store_dword v21, v0, s[0:3], 0 offen offset:160
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:164
+; GISEL-NEXT:    buffer_store_dword v22, v0, s[0:3], 0 offen offset:168
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:172
+; GISEL-NEXT:    buffer_store_dword v23, v0, s[0:3], 0 offen offset:176
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:180
+; GISEL-NEXT:    buffer_store_dword v24, v0, s[0:3], 0 offen offset:184
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:188
+; GISEL-NEXT:    buffer_store_dword v25, v0, s[0:3], 0 offen offset:192
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:196
+; GISEL-NEXT:    buffer_store_dword v26, v0, s[0:3], 0 offen offset:200
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:204
+; GISEL-NEXT:    buffer_store_dword v27, v0, s[0:3], 0 offen offset:208
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:212
+; GISEL-NEXT:    buffer_store_dword v28, v0, s[0:3], 0 offen offset:216
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:220
+; GISEL-NEXT:    buffer_store_dword v29, v0, s[0:3], 0 offen offset:224
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:228
+; GISEL-NEXT:    buffer_store_dword v30, v0, s[0:3], 0 offen offset:232
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:236
+; GISEL-NEXT:    s_waitcnt vmcnt(57)
+; GISEL-NEXT:    buffer_store_dword v1, v0, s[0:3], 0 offen offset:240
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:244
+; GISEL-NEXT:    s_waitcnt vmcnt(58)
+; GISEL-NEXT:    buffer_store_dword v2, v0, s[0:3], 0 offen offset:248
+; GISEL-NEXT:    buffer_store_dword v3, v0, s[0:3], 0 offen offset:252
+; GISEL-NEXT:    s_waitcnt vmcnt(0)
+; GISEL-NEXT:    s_setpc_b64 s[30:31]
+  %1 = addrspacecast nonnull <32 x ptr addrspace(3)> %ptr to <32 x ptr>
+  ret <32 x ptr> %1
+}
+
+; Two nonnull casts of the same flat source to 
diff erent destination address
+; spaces must not be CSEd together despite sharing an operand and the flag.
+define void @nonnull_casts_
diff erent_dest(i64 %i) {
+; CHECK-LABEL: nonnull_casts_
diff erent_dest:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT:    v_mov_b32_e32 v1, 7
+; CHECK-NEXT:    ds_write_b32 v0, v1
+; CHECK-NEXT:    v_mov_b32_e32 v1, 8
+; CHECK-NEXT:    buffer_store_dword v1, v0, s[0:3], 0 offen
+; CHECK-NEXT:    s_waitcnt vmcnt(0) lgkmcnt(0)
+; CHECK-NEXT:    s_setpc_b64 s[30:31]
+  %flat = inttoptr i64 %i to ptr
+  %local = addrspacecast nonnull ptr %flat to ptr addrspace(3)
+  %priv = addrspacecast nonnull ptr %flat to ptr addrspace(5)
+  store volatile i32 7, ptr addrspace(3) %local, align 4
+  store volatile i32 8, ptr addrspace(5) %priv, align 4
+  ret void
+}
+
+; The inverted case: nonnull casts to flat from two 
diff erent source address
+; spaces. Each source has its own null value, so the casts are distinct.
+define void @nonnull_casts_
diff erent_src(i32 %i) {
+; DAGISEL-LABEL: nonnull_casts_
diff erent_src:
+; DAGISEL:       ; %bb.0:
+; DAGISEL-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; DAGISEL-NEXT:    s_mov_b64 s[4:5], src_shared_base
+; DAGISEL-NEXT:    s_mov_b64 s[6:7], src_private_base
+; DAGISEL-NEXT:    v_mov_b32_e32 v1, s5
+; DAGISEL-NEXT:    v_mov_b32_e32 v4, 7
+; DAGISEL-NEXT:    v_mov_b32_e32 v2, v0
+; DAGISEL-NEXT:    v_mov_b32_e32 v3, s7
+; DAGISEL-NEXT:    flat_store_dword v[0:1], v4
+; DAGISEL-NEXT:    s_waitcnt vmcnt(0)
+; DAGISEL-NEXT:    v_mov_b32_e32 v0, 8
+; DAGISEL-NEXT:    flat_store_dword v[2:3], v0
+; DAGISEL-NEXT:    s_waitcnt vmcnt(0) lgkmcnt(0)
+; DAGISEL-NEXT:    s_setpc_b64 s[30:31]
+;
+; GISEL-LABEL: nonnull_casts_
diff erent_src:
+; GISEL:       ; %bb.0:
+; GISEL-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GISEL-NEXT:    s_mov_b64 s[4:5], src_shared_base
+; GISEL-NEXT:    s_mov_b64 s[6:7], src_private_base
+; GISEL-NEXT:    v_mov_b32_e32 v1, s5
+; GISEL-NEXT:    v_mov_b32_e32 v4, 7
+; GISEL-NEXT:    v_mov_b32_e32 v3, s7
+; GISEL-NEXT:    v_mov_b32_e32 v2, v0
+; GISEL-NEXT:    flat_store_dword v[0:1], v4
+; GISEL-NEXT:    s_waitcnt vmcnt(0)
+; GISEL-NEXT:    v_mov_b32_e32 v0, 8
+; GISEL-NEXT:    flat_store_dword v[2:3], v0
+; GISEL-NEXT:    s_waitcnt vmcnt(0) lgkmcnt(0)
+; GISEL-NEXT:    s_setpc_b64 s[30:31]
+  %local = inttoptr i32 %i to ptr addrspace(3)
+  %priv = inttoptr i32 %i to ptr addrspace(5)
+  %flat.local = addrspacecast nonnull ptr addrspace(3) %local to ptr
+  %flat.priv = addrspacecast nonnull ptr addrspace(5) %priv to ptr
+  store volatile i32 7, ptr %flat.local, align 4
+  store volatile i32 8, ptr %flat.priv, align 4
+  ret void
+}

diff  --git a/llvm/test/CodeGen/MIR/AMDGPU/addrspacecast-nonnull.mir b/llvm/test/CodeGen/MIR/AMDGPU/addrspacecast-nonnull.mir
new file mode 100644
index 0000000000000..d30f7f44cf937
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/AMDGPU/addrspacecast-nonnull.mir
@@ -0,0 +1,23 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=amdgpu7.00-amd-amdhsa -run-pass=none -o - %s | FileCheck %s
+
+# Check that the nonnull MIFlag on G_ADDRSPACE_CAST round-trips through the MIR
+# printer and parser.
+
+---
+name: nonnull_addrspacecast
+body: |
+  bb.0:
+    liveins: $vgpr0
+    ; CHECK-LABEL: name: nonnull_addrspacecast
+    ; CHECK: liveins: $vgpr0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0
+    ; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(p3) = G_INTTOPTR [[COPY]](s32)
+    ; CHECK-NEXT: [[ADDRSPACE_CAST:%[0-9]+]]:_(p0) = nonnull G_ADDRSPACE_CAST [[INTTOPTR]](p3)
+    ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[ADDRSPACE_CAST]](p0)
+    %0:_(s32) = COPY $vgpr0
+    %1:_(p3) = G_INTTOPTR %0
+    %2:_(p0) = nonnull G_ADDRSPACE_CAST %1
+    $vgpr0_vgpr1 = COPY %2
+...

diff  --git a/llvm/utils/UpdateTestChecks/mir.py b/llvm/utils/UpdateTestChecks/mir.py
index e5f381edcb343..ff143177e65d9 100644
--- a/llvm/utils/UpdateTestChecks/mir.py
+++ b/llvm/utils/UpdateTestChecks/mir.py
@@ -21,7 +21,8 @@
 MI_FLAGS_STR = (
     r"(frame-setup |frame-destroy |nnan |ninf |nsz |arcp |contract |afn "
     r"|reassoc |nuw |nsw |exact |nofpexcept |nomerge |unpredictable "
-    r"|noconvergent |nneg |disjoint |nusw |samesign |inbounds |lr-split )*"
+    r"|noconvergent |nneg |disjoint |nusw |samesign |inbounds |lr-split "
+    r"|nonnull )*"
 )
 VREG_DEF_FLAGS_STR = r"(?:dead |undef )*"
 


        


More information about the llvm-commits mailing list