[llvm] [SelectionDAG][NVPTX] Allow targets to configure CSE strategy (PR #192812)

Princeton Ferro via llvm-commits llvm-commits at lists.llvm.org
Sat May 9 20:58:53 PDT 2026


https://github.com/Prince781 updated https://github.com/llvm/llvm-project/pull/192812

>From efc79d2aa5ef9e9b50ad60d9318784c1efef7d05 Mon Sep 17 00:00:00 2001
From: Princeton Ferro <pferro at nvidia.com>
Date: Fri, 10 Apr 2026 19:49:11 -0700
Subject: [PATCH 1/2] [SelectionDAG] Add target-pluggable CSE map via
 SDNodeCSEMap

SelectionDAG currently uses a fixed FoldingSet<SDNode> for CSE.
Introduces SDNodeCSEMap, an abstract interface owned by SelectionDAG
via unique_ptr, and a createCSEMap() factory on SelectionDAGTargetInfo
(called once in SelectionDAG::init()).

The default implementation, DefaultSDNodeMap, wraps FoldingSet<SDNode>
with no behavior change for any existing target.

NVPTX overrides this with NVPTXSDNodeCSEMap, which at -O0 augments
each node's CSE key with its DebugLoc. This prevents CSE from silently
merging identical operations at different source locations, improving
single-step debug fidelity. Constants are always CSE'd. At higher opt
levels profileDebugLoc is a no-op, restoring normal CSE behavior.

SelectionDAG::FindNodeOrInsertPos is unified to a single opcode-taking
signature so the CSE map has all the context it needs; all call sites
are updated to pass the opcode they already have.

DebugLoc::Profile() is added as the primitive that stamps filename,
line, and column into a FoldingSetNodeID.
---
 llvm/include/llvm/CodeGen/SelectionDAG.h      |  40 ++-
 .../llvm/CodeGen/SelectionDAGTargetInfo.h     |   7 +
 llvm/include/llvm/IR/DebugLoc.h               |   4 +
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 276 ++++++++++--------
 llvm/lib/IR/DebugLoc.cpp                      |   8 +
 .../Target/NVPTX/NVPTXSelectionDAGInfo.cpp    |  78 +++++
 llvm/lib/Target/NVPTX/NVPTXSelectionDAGInfo.h |   2 +
 7 files changed, 276 insertions(+), 139 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index fba44dca6800c..e1bb7f24665ec 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -47,6 +47,7 @@
 #include <cstdint>
 #include <functional>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <tuple>
@@ -217,6 +218,26 @@ class SDDbgInfo {
 
 LLVM_ABI void checkForCycles(const SelectionDAG *DAG, bool force = false);
 
+/// Abstract CSE map for SDNodes.  Targets can override
+/// SelectionDAGTargetInfo::createCSEMap() to supply a custom implementation.
+class SDNodeCSEMap {
+public:
+  virtual ~SDNodeCSEMap() = default;
+
+  /// Look up ID in the CSE map, or prepare an insertion point.
+  /// Opcode and DL are forwarded so the implementation can apply
+  /// target-specific CSE policies.
+  virtual SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID,
+                                      unsigned Opcode, const SDLoc &DL,
+                                      void *&InsertPos) = 0;
+  virtual void InsertNode(SDNode *N, void *InsertPos) = 0;
+  /// Returns true if N was present.
+  virtual bool RemoveNode(SDNode *N) = 0;
+  /// Insert N, or return the existing equal node.
+  virtual SDNode *GetOrInsertNode(SDNode *N) = 0;
+  virtual void clear() = 0;
+};
+
 /// This is used to represent a portion of an LLVM function in a low-level
 /// Data Dependence DAG representation suitable for instruction selection.
 /// This DAG is constructed as the first step of instruction selection in order
@@ -281,9 +302,9 @@ class SelectionDAG {
   /// Pool allocation for nodes.
   NodeAllocatorType NodeAllocator;
 
-  /// This structure is used to memoize nodes, automatically performing
-  /// CSE with existing nodes when a duplicate is requested.
-  FoldingSet<SDNode> CSEMap;
+  /// CSE map for SDNode deduplication; created by
+  /// SelectionDAGTargetInfo::createCSEMap().
+  std::unique_ptr<SDNodeCSEMap> CSEMap;
 
   /// Pool allocation for machine-opcode SDNode operands.
   BumpPtrAllocator OperandAllocator;
@@ -2811,16 +2832,11 @@ class SelectionDAG {
   void allnodes_clear();
 
   /// Look up the node specified by ID in CSEMap.  If it exists, return it.  If
-  /// not, return the insertion token that will make insertion faster.  This
-  /// overload is for nodes other than Constant or ConstantFP, use the other one
-  /// for those.
-  SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos);
-
-  /// Look up the node specified by ID in CSEMap.  If it exists, return it.  If
-  /// not, return the insertion token that will make insertion faster.  Performs
-  /// additional processing for constant nodes.
+  /// not, return the insertion token that will make insertion faster.
+  /// Opcode is used by target CSE policies to apply node-kind-specific rules.
+  /// Use SDLoc() for DL when there is no associated debug location.
   SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, const SDLoc &DL,
-                              void *&InsertPos);
+                              void *&InsertPos, unsigned Opcode);
 
   /// Maps to auto-CSE operations.
   std::vector<CondCodeSDNode*> CondCodeNodes;
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h b/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h
index 64f63d5b2190f..7d8375c1f32bb 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h
@@ -19,11 +19,13 @@
 #include "llvm/CodeGen/SDNodeInfo.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/Support/CodeGen.h"
+#include <memory>
 #include <utility>
 
 namespace llvm {
 
 class CallInst;
+class SDNodeCSEMap;
 class SelectionDAG;
 
 //===----------------------------------------------------------------------===//
@@ -204,6 +206,11 @@ class SelectionDAGTargetInfo {
   virtual bool disableGenericCombines(CodeGenOptLevel OptLevel) const {
     return false;
   }
+
+  /// Returns the CSE map to use for this SelectionDAG.
+  /// Called once during SelectionDAG::init().
+  LLVM_ABI virtual std::unique_ptr<SDNodeCSEMap>
+  createCSEMap(SelectionDAG &DAG) const;
 };
 
 /// Proxy class that targets should inherit from if they wish to use
diff --git a/llvm/include/llvm/IR/DebugLoc.h b/llvm/include/llvm/IR/DebugLoc.h
index 484adbb6e6a6c..c501f4bb4dc70 100644
--- a/llvm/include/llvm/IR/DebugLoc.h
+++ b/llvm/include/llvm/IR/DebugLoc.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_IR_DEBUGLOC_H
 #define LLVM_IR_DEBUGLOC_H
 
+#include "llvm/ADT/FoldingSet.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/IR/TrackingMDRef.h"
 #include "llvm/Support/Compiler.h"
@@ -293,6 +294,9 @@ class DebugLoc {
   LLVM_ABI bool isImplicitCode() const;
   LLVM_ABI void setImplicitCode(bool ImplicitCode);
 
+  /// Add the filename, line, and column to ID.
+  LLVM_ABI void Profile(FoldingSetNodeID &ID) const;
+
   bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; }
   bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; }
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index a221df567a10f..a0627675b3c28 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -84,6 +84,30 @@
 using namespace llvm;
 using namespace llvm::SDPatternMatch;
 
+namespace {
+/// Default CSE map: thin wrapper around FoldingSet<SDNode>.
+class DefaultSDNodeMap final : public SDNodeCSEMap {
+  FoldingSet<SDNode> FS;
+
+public:
+  SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, unsigned /*Opcode*/,
+                              const SDLoc & /*DL*/, void *&InsertPos) override {
+    return FS.FindNodeOrInsertPos(ID, InsertPos);
+  }
+  void InsertNode(SDNode *N, void *InsertPos) override {
+    FS.InsertNode(N, InsertPos);
+  }
+  bool RemoveNode(SDNode *N) override { return FS.RemoveNode(N); }
+  SDNode *GetOrInsertNode(SDNode *N) override { return FS.GetOrInsertNode(N); }
+  void clear() override { FS.clear(); }
+};
+} // namespace
+
+std::unique_ptr<SDNodeCSEMap>
+SelectionDAGTargetInfo::createCSEMap(SelectionDAG &) const {
+  return std::make_unique<DefaultSDNodeMap>();
+}
+
 /// makeVTList - Return an instance of the SDVTList struct initialized with the
 /// specified members.
 static SDVTList makeVTList(const EVT *VTs, unsigned NumVTs) {
@@ -1300,7 +1324,7 @@ bool SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) {
     // Remove it from the CSE Map.
     assert(N->getOpcode() != ISD::DELETED_NODE && "DELETED_NODE in CSEMap!");
     assert(N->getOpcode() != ISD::EntryToken && "EntryToken in CSEMap!");
-    Erased = CSEMap.RemoveNode(N);
+    Erased = CSEMap->RemoveNode(N);
     break;
   }
 #ifndef NDEBUG
@@ -1326,7 +1350,7 @@ SelectionDAG::AddModifiedNodeToCSEMaps(SDNode *N) {
   // For node types that aren't CSE'd, just act as if no identical node
   // already exists.
   if (!doNotCSE(N)) {
-    SDNode *Existing = CSEMap.GetOrInsertNode(N);
+    SDNode *Existing = CSEMap->GetOrInsertNode(N);
     if (Existing != N) {
       // If there was already an existing matching node, use ReplaceAllUsesWith
       // to replace the dead one with the existing one.  This can cause
@@ -1362,7 +1386,7 @@ SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, SDValue Op,
   FoldingSetNodeID ID;
   AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops);
   AddNodeIDCustom(ID, N);
-  SDNode *Node = FindNodeOrInsertPos(ID, SDLoc(N), InsertPos);
+  SDNode *Node = FindNodeOrInsertPos(ID, SDLoc(N), InsertPos, N->getOpcode());
   if (Node)
     Node->intersectFlagsWith(N->getFlags());
   return Node;
@@ -1382,7 +1406,7 @@ SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N,
   FoldingSetNodeID ID;
   AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops);
   AddNodeIDCustom(ID, N);
-  SDNode *Node = FindNodeOrInsertPos(ID, SDLoc(N), InsertPos);
+  SDNode *Node = FindNodeOrInsertPos(ID, SDLoc(N), InsertPos, N->getOpcode());
   if (Node)
     Node->intersectFlagsWith(N->getFlags());
   return Node;
@@ -1400,7 +1424,7 @@ SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, ArrayRef<SDValue> Ops,
   FoldingSetNodeID ID;
   AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops);
   AddNodeIDCustom(ID, N);
-  SDNode *Node = FindNodeOrInsertPos(ID, SDLoc(N), InsertPos);
+  SDNode *Node = FindNodeOrInsertPos(ID, SDLoc(N), InsertPos, N->getOpcode());
   if (Node)
     Node->intersectFlagsWith(N->getFlags());
   return Node;
@@ -1434,6 +1458,7 @@ void SelectionDAG::init(MachineFunction &NewMF,
   ORE = &NewORE;
   TLI = getSubtarget().getTargetLowering();
   TSI = getSubtarget().getSelectionDAGInfo();
+  CSEMap = TSI->createCSEMap(*this);
   LibInfo = LibraryInfo;
   Libcalls = LibcallsInfo;
   Context = &MF->getFunction().getContext();
@@ -1466,23 +1491,9 @@ void SelectionDAG::allnodes_clear() {
 }
 
 SDNode *SelectionDAG::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
-                                          void *&InsertPos) {
-  SDNode *N = CSEMap.FindNodeOrInsertPos(ID, InsertPos);
-  if (N) {
-    switch (N->getOpcode()) {
-    default: break;
-    case ISD::Constant:
-    case ISD::ConstantFP:
-      llvm_unreachable("Querying for Constant and ConstantFP nodes requires "
-                       "debug location.  Use another overload.");
-    }
-  }
-  return N;
-}
-
-SDNode *SelectionDAG::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
-                                          const SDLoc &DL, void *&InsertPos) {
-  SDNode *N = CSEMap.FindNodeOrInsertPos(ID, InsertPos);
+                                          const SDLoc &DL, void *&InsertPos,
+                                          unsigned Opcode) {
+  SDNode *N = CSEMap->FindNodeOrInsertPos(ID, Opcode, DL, InsertPos);
   if (N) {
     switch (N->getOpcode()) {
     case ISD::Constant:
@@ -1509,7 +1520,7 @@ void SelectionDAG::clear() {
   allnodes_clear();
   OperandRecycler.clear(OperandAllocator);
   OperandAllocator.Reset();
-  CSEMap.clear();
+  CSEMap->clear();
 
   ExtendedValueTypeNodes.clear();
   ExternalSymbols.clear();
@@ -1833,7 +1844,7 @@ SDValue SelectionDAG::getConstant(const ConstantInt &Val, const SDLoc &DL,
   ID.AddBoolean(isO);
   void *IP = nullptr;
   SDNode *N = nullptr;
-  if ((N = FindNodeOrInsertPos(ID, DL, IP)))
+  if ((N = FindNodeOrInsertPos(ID, DL, IP, Opc)))
     if (!VT.isVector())
       return SDValue(N, 0);
 
@@ -1841,7 +1852,7 @@ SDValue SelectionDAG::getConstant(const ConstantInt &Val, const SDLoc &DL,
     N = newSDNode<ConstantSDNode>(isT, isO, Elt, VTs);
     if (!isT)
       N->setDebugLoc(DL.getDebugLoc());
-    CSEMap.InsertNode(N, IP);
+    CSEMap->InsertNode(N, IP);
     InsertNode(N);
     NewSDValueDbgMsg(SDValue(N, 0), "Creating constant: ", this);
   }
@@ -1914,13 +1925,13 @@ SDValue SelectionDAG::getConstantFP(const ConstantFP &V, const SDLoc &DL,
   ID.AddPointer(Elt);
   void *IP = nullptr;
   SDNode *N = nullptr;
-  if ((N = FindNodeOrInsertPos(ID, DL, IP)))
+  if ((N = FindNodeOrInsertPos(ID, DL, IP, Opc)))
     if (!VT.isVector())
       return SDValue(N, 0);
 
   if (!N) {
     N = newSDNode<ConstantFPSDNode>(isTarget, Elt, VTs);
-    CSEMap.InsertNode(N, IP);
+    CSEMap->InsertNode(N, IP);
     InsertNode(N);
   }
 
@@ -1973,13 +1984,13 @@ SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV, const SDLoc &DL,
   ID.AddInteger(Offset);
   ID.AddInteger(TargetFlags);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP, Opc))
     return SDValue(E, 0);
 
   auto *N = newSDNode<GlobalAddressSDNode>(
       Opc, DL.getIROrder(), DL.getDebugLoc(), GV, VTs, Offset, TargetFlags);
-  CSEMap.InsertNode(N, IP);
-    InsertNode(N);
+  CSEMap->InsertNode(N, IP);
+  InsertNode(N);
   return SDValue(N, 0);
 }
 
@@ -1989,11 +2000,12 @@ SDValue SelectionDAG::getDeactivationSymbol(const GlobalValue *GV) {
   AddNodeIDNode(ID, ISD::DEACTIVATION_SYMBOL, VTs, {});
   ID.AddPointer(GV);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP))
+  if (SDNode *E =
+          FindNodeOrInsertPos(ID, SDLoc(), IP, ISD::DEACTIVATION_SYMBOL))
     return SDValue(E, 0);
 
   auto *N = newSDNode<DeactivationSymbolSDNode>(GV, VTs);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -2005,11 +2017,11 @@ SDValue SelectionDAG::getFrameIndex(int FI, EVT VT, bool isTarget) {
   AddNodeIDNode(ID, Opc, VTs, {});
   ID.AddInteger(FI);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, Opc))
     return SDValue(E, 0);
 
   auto *N = newSDNode<FrameIndexSDNode>(FI, VTs, isTarget);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -2025,11 +2037,11 @@ SDValue SelectionDAG::getJumpTable(int JTI, EVT VT, bool isTarget,
   ID.AddInteger(JTI);
   ID.AddInteger(TargetFlags);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, Opc))
     return SDValue(E, 0);
 
   auto *N = newSDNode<JumpTableSDNode>(JTI, VTs, isTarget, TargetFlags);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -2059,12 +2071,12 @@ SDValue SelectionDAG::getConstantPool(const Constant *C, EVT VT,
   ID.AddPointer(C);
   ID.AddInteger(TargetFlags);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, Opc))
     return SDValue(E, 0);
 
   auto *N = newSDNode<ConstantPoolSDNode>(isTarget, C, VTs, Offset, *Alignment,
                                           TargetFlags);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V = SDValue(N, 0);
   NewSDValueDbgMsg(V, "Creating new constant pool: ", this);
@@ -2087,12 +2099,12 @@ SDValue SelectionDAG::getConstantPool(MachineConstantPoolValue *C, EVT VT,
   C->addSelectionDAGCSEId(ID);
   ID.AddInteger(TargetFlags);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, Opc))
     return SDValue(E, 0);
 
   auto *N = newSDNode<ConstantPoolSDNode>(isTarget, C, VTs, Offset, *Alignment,
                                           TargetFlags);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -2102,11 +2114,11 @@ SDValue SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) {
   AddNodeIDNode(ID, ISD::BasicBlock, getVTList(MVT::Other), {});
   ID.AddPointer(MBB);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, ISD::BasicBlock))
     return SDValue(E, 0);
 
   auto *N = newSDNode<BasicBlockSDNode>(MBB);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -2401,7 +2413,7 @@ SDValue SelectionDAG::getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1,
     ID.AddInteger(MaskVec[i]);
 
   void* IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::VECTOR_SHUFFLE))
     return SDValue(E, 0);
 
   // Allocate the mask array for the node out of the BumpPtrAllocator, since
@@ -2414,7 +2426,7 @@ SDValue SelectionDAG::getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1,
                                            dl.getDebugLoc(), MaskAlloc);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V = SDValue(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -2437,12 +2449,12 @@ SDValue SelectionDAG::getRegister(Register Reg, EVT VT) {
   AddNodeIDNode(ID, ISD::Register, VTs, {});
   ID.AddInteger(Reg.id());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, ISD::Register))
     return SDValue(E, 0);
 
   auto *N = newSDNode<RegisterSDNode>(Reg, VTs);
   N->SDNodeBits.IsDivergent = TLI->isSDNodeSourceOfDivergence(N, FLI, UA);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -2452,11 +2464,11 @@ SDValue SelectionDAG::getRegisterMask(const uint32_t *RegMask) {
   AddNodeIDNode(ID, ISD::RegisterMask, getVTList(MVT::Untyped), {});
   ID.AddPointer(RegMask);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, ISD::RegisterMask))
     return SDValue(E, 0);
 
   auto *N = newSDNode<RegisterMaskSDNode>(RegMask);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -2473,14 +2485,14 @@ SDValue SelectionDAG::getLabelNode(unsigned Opcode, const SDLoc &dl,
   AddNodeIDNode(ID, Opcode, getVTList(MVT::Other), Ops);
   ID.AddPointer(Label);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, Opcode))
     return SDValue(E, 0);
 
   auto *N =
       newSDNode<LabelSDNode>(Opcode, dl.getIROrder(), dl.getDebugLoc(), Label);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -2497,11 +2509,11 @@ SDValue SelectionDAG::getBlockAddress(const BlockAddress *BA, EVT VT,
   ID.AddInteger(Offset);
   ID.AddInteger(TargetFlags);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, Opc))
     return SDValue(E, 0);
 
   auto *N = newSDNode<BlockAddressSDNode>(Opc, VTs, BA, Offset, TargetFlags);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -2512,11 +2524,11 @@ SDValue SelectionDAG::getSrcValue(const Value *V) {
   ID.AddPointer(V);
 
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, ISD::SRCVALUE))
     return SDValue(E, 0);
 
   auto *N = newSDNode<SrcValueSDNode>(V);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -2527,11 +2539,11 @@ SDValue SelectionDAG::getMDNode(const MDNode *MD) {
   ID.AddPointer(MD);
 
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, ISD::MDNODE_SDNODE))
     return SDValue(E, 0);
 
   auto *N = newSDNode<MDNodeSDNode>(MD);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -2553,14 +2565,14 @@ SDValue SelectionDAG::getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr,
   ID.AddInteger(DestAS);
 
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::ADDRSPACECAST))
     return SDValue(E, 0);
 
   auto *N = newSDNode<AddrSpaceCastSDNode>(dl.getIROrder(), dl.getDebugLoc(),
                                            VTs, SrcAS, DestAS);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   return SDValue(N, 0);
 }
@@ -6964,11 +6976,11 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT) {
   FoldingSetNodeID ID;
   AddNodeIDNode(ID, Opcode, VTs, {});
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP, Opcode))
     return SDValue(E, 0);
 
   auto *N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
 
   InsertNode(N);
   SDValue V = SDValue(N, 0);
@@ -7345,7 +7357,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     FoldingSetNodeID ID;
     AddNodeIDNode(ID, Opcode, VTs, Ops);
     void *IP = nullptr;
-    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
+    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP, Opcode)) {
       E->intersectFlagsWith(Flags);
       return SDValue(E, 0);
     }
@@ -7353,7 +7365,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
     N->setFlags(Flags);
     createOperands(N, Ops);
-    CSEMap.InsertNode(N, IP);
+    CSEMap->InsertNode(N, IP);
   } else {
     N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
     createOperands(N, Ops);
@@ -8137,14 +8149,14 @@ SDValue SelectionDAG::getAssertAlign(const SDLoc &DL, SDValue Val, Align A) {
   ID.AddInteger(A.value());
 
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP, ISD::AssertAlign))
     return SDValue(E, 0);
 
   auto *N =
       newSDNode<AssertAlignSDNode>(DL.getIROrder(), DL.getDebugLoc(), VTs, A);
   createOperands(N, {Val});
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
 
   SDValue V(N, 0);
@@ -8738,7 +8750,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     FoldingSetNodeID ID;
     AddNodeIDNode(ID, Opcode, VTs, Ops);
     void *IP = nullptr;
-    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
+    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP, Opcode)) {
       E->intersectFlagsWith(Flags);
       return SDValue(E, 0);
     }
@@ -8746,7 +8758,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
     N->setFlags(Flags);
     createOperands(N, Ops);
-    CSEMap.InsertNode(N, IP);
+    CSEMap->InsertNode(N, IP);
   } else {
     N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
     createOperands(N, Ops);
@@ -9006,7 +9018,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     FoldingSetNodeID ID;
     AddNodeIDNode(ID, Opcode, VTs, Ops);
     void *IP = nullptr;
-    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
+    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP, Opcode)) {
       E->intersectFlagsWith(Flags);
       return SDValue(E, 0);
     }
@@ -9014,7 +9026,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
     N->setFlags(Flags);
     createOperands(N, Ops);
-    CSEMap.InsertNode(N, IP);
+    CSEMap->InsertNode(N, IP);
   } else {
     N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
     createOperands(N, Ops);
@@ -10216,7 +10228,8 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void* IP = nullptr;
-  if (auto *E = cast_or_null<AtomicSDNode>(FindNodeOrInsertPos(ID, dl, IP))) {
+  if (auto *E =
+          cast_or_null<AtomicSDNode>(FindNodeOrInsertPos(ID, dl, IP, Opcode))) {
     E->refineAlignment(MMO);
     E->refineRanges(MMO);
     return SDValue(E, 0);
@@ -10226,7 +10239,7 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT,
                                     VTList, MemVT, MMO, ExtType);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -10356,7 +10369,7 @@ SDValue SelectionDAG::getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl,
       ID.AddInteger(MMO->getFlags());
     }
     void *IP = nullptr;
-    if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
+    if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, Opcode)) {
       cast<MemIntrinsicSDNode>(E)->refineAlignment(MMOs);
       return SDValue(E, 0);
     }
@@ -10364,7 +10377,7 @@ SDValue SelectionDAG::getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl,
     N = newSDNode<MemIntrinsicSDNode>(Opcode, dl.getIROrder(), dl.getDebugLoc(),
                                       VTList, MemVT, MemRefs);
     createOperands(N, Ops);
-    CSEMap.InsertNode(N, IP);
+    CSEMap->InsertNode(N, IP);
   } else {
     N = newSDNode<MemIntrinsicSDNode>(Opcode, dl.getIROrder(), dl.getDebugLoc(),
                                       VTList, MemVT, MemRefs);
@@ -10390,13 +10403,13 @@ SDValue SelectionDAG::getLifetimeNode(bool IsStart, const SDLoc &dl,
   AddNodeIDNode(ID, Opcode, VTs, Ops);
   ID.AddInteger(FrameIndex);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, Opcode))
     return SDValue(E, 0);
 
   LifetimeSDNode *N =
       newSDNode<LifetimeSDNode>(Opcode, dl.getIROrder(), dl.getDebugLoc(), VTs);
   createOperands(N, Ops);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -10414,13 +10427,13 @@ SDValue SelectionDAG::getPseudoProbeNode(const SDLoc &Dl, SDValue Chain,
   ID.AddInteger(Guid);
   ID.AddInteger(Index);
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, Dl, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, Dl, IP, Opcode))
     return SDValue(E, 0);
 
   auto *N = newSDNode<PseudoProbeSDNode>(
       Opcode, Dl.getIROrder(), Dl.getDebugLoc(), VTs, Guid, Index, Attr);
   createOperands(N, Ops);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -10531,7 +10544,8 @@ SDValue SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (auto *E = cast_or_null<LoadSDNode>(FindNodeOrInsertPos(ID, dl, IP))) {
+  if (auto *E = cast_or_null<LoadSDNode>(
+          FindNodeOrInsertPos(ID, dl, IP, ISD::LOAD))) {
     E->refineAlignment(MMO);
     E->refineRanges(MMO);
     return SDValue(E, 0);
@@ -10540,7 +10554,7 @@ SDValue SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
                                   ExtType, MemVT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -10658,7 +10672,7 @@ SDValue SelectionDAG::getStore(SDValue Chain, const SDLoc &dl, SDValue Val,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::STORE)) {
     cast<StoreSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -10666,7 +10680,7 @@ SDValue SelectionDAG::getStore(SDValue Chain, const SDLoc &dl, SDValue Val,
                                    IsTruncating, SVT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -10756,7 +10770,8 @@ SDValue SelectionDAG::getLoadVP(ISD::MemIndexedMode AM,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (auto *E = cast_or_null<VPLoadSDNode>(FindNodeOrInsertPos(ID, dl, IP))) {
+  if (auto *E = cast_or_null<VPLoadSDNode>(
+          FindNodeOrInsertPos(ID, dl, IP, ISD::VP_LOAD))) {
     E->refineAlignment(MMO);
     E->refineRanges(MMO);
     return SDValue(E, 0);
@@ -10765,7 +10780,7 @@ SDValue SelectionDAG::getLoadVP(ISD::MemIndexedMode AM,
                                     ExtType, IsExpanding, MemVT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -10854,7 +10869,7 @@ SDValue SelectionDAG::getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::VP_STORE)) {
     cast<VPStoreSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -10862,7 +10877,7 @@ SDValue SelectionDAG::getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val,
                                      IsTruncating, IsCompressing, MemVT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -10924,7 +10939,7 @@ SDValue SelectionDAG::getTruncStoreVP(SDValue Chain, const SDLoc &dl,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::VP_STORE)) {
     cast<VPStoreSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -10933,7 +10948,7 @@ SDValue SelectionDAG::getTruncStoreVP(SDValue Chain, const SDLoc &dl,
                                ISD::UNINDEXED, true, IsCompressing, SVT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -10955,7 +10970,7 @@ SDValue SelectionDAG::getIndexedStoreVP(SDValue OrigStore, const SDLoc &dl,
   ID.AddInteger(ST->getPointerInfo().getAddrSpace());
   ID.AddInteger(ST->getMemOperand()->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::VP_STORE))
     return SDValue(E, 0);
 
   auto *N = newSDNode<VPStoreSDNode>(
@@ -10963,7 +10978,7 @@ SDValue SelectionDAG::getIndexedStoreVP(SDValue OrigStore, const SDLoc &dl,
       ST->isCompressingStore(), ST->getMemoryVT(), ST->getMemOperand());
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -10988,7 +11003,8 @@ SDValue SelectionDAG::getStridedLoadVP(
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
 
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
+  if (SDNode *E =
+          FindNodeOrInsertPos(ID, DL, IP, ISD::EXPERIMENTAL_VP_STRIDED_LOAD)) {
     cast<VPStridedLoadSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -10997,7 +11013,7 @@ SDValue SelectionDAG::getStridedLoadVP(
       newSDNode<VPStridedLoadSDNode>(DL.getIROrder(), DL.getDebugLoc(), VTs, AM,
                                      ExtType, IsExpanding, MemVT, MMO);
   createOperands(N, Ops);
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11043,7 +11059,8 @@ SDValue SelectionDAG::getStridedStoreVP(SDValue Chain, const SDLoc &DL,
       DL.getIROrder(), VTs, AM, IsTruncating, IsCompressing, MemVT, MMO));
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
+  if (SDNode *E =
+          FindNodeOrInsertPos(ID, DL, IP, ISD::EXPERIMENTAL_VP_STRIDED_STORE)) {
     cast<VPStridedStoreSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -11052,7 +11069,7 @@ SDValue SelectionDAG::getStridedStoreVP(SDValue Chain, const SDLoc &DL,
                                             IsCompressing, MemVT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11092,7 +11109,8 @@ SDValue SelectionDAG::getTruncStridedStoreVP(SDValue Chain, const SDLoc &DL,
       DL.getIROrder(), VTs, ISD::UNINDEXED, true, IsCompressing, SVT, MMO));
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
+  if (SDNode *E =
+          FindNodeOrInsertPos(ID, DL, IP, ISD::EXPERIMENTAL_VP_STRIDED_STORE)) {
     cast<VPStridedStoreSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -11101,7 +11119,7 @@ SDValue SelectionDAG::getTruncStridedStoreVP(SDValue Chain, const SDLoc &DL,
                                             IsCompressing, SVT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11121,7 +11139,7 @@ SDValue SelectionDAG::getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::VP_GATHER)) {
     cast<VPGatherSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -11144,7 +11162,7 @@ SDValue SelectionDAG::getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl,
          N->getScale()->getAsAPIntVal().isPowerOf2() &&
          "Scale should be a constant power of 2");
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11165,7 +11183,7 @@ SDValue SelectionDAG::getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::VP_SCATTER)) {
     cast<VPScatterSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -11188,7 +11206,7 @@ SDValue SelectionDAG::getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl,
          N->getScale()->getAsAPIntVal().isPowerOf2() &&
          "Scale should be a constant power of 2");
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11215,7 +11233,7 @@ SDValue SelectionDAG::getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::MLOAD)) {
     cast<MaskedLoadSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -11223,7 +11241,7 @@ SDValue SelectionDAG::getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain,
                                         AM, ExtTy, isExpanding, MemVT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11263,7 +11281,7 @@ SDValue SelectionDAG::getMaskedStore(SDValue Chain, const SDLoc &dl,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::MSTORE)) {
     cast<MaskedStoreSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -11272,7 +11290,7 @@ SDValue SelectionDAG::getMaskedStore(SDValue Chain, const SDLoc &dl,
                                    IsTruncating, IsCompressing, MemVT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11305,7 +11323,7 @@ SDValue SelectionDAG::getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::MGATHER)) {
     cast<MaskedGatherSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -11330,7 +11348,7 @@ SDValue SelectionDAG::getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl,
          N->getScale()->getAsAPIntVal().isPowerOf2() &&
          "Scale should be a constant power of 2");
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11352,7 +11370,7 @@ SDValue SelectionDAG::getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::MSCATTER)) {
     cast<MaskedScatterSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -11376,7 +11394,7 @@ SDValue SelectionDAG::getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl,
          N->getScale()->getAsAPIntVal().isPowerOf2() &&
          "Scale should be a constant power of 2");
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11397,7 +11415,8 @@ SDValue SelectionDAG::getMaskedHistogram(SDVTList VTs, EVT MemVT,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
+  if (SDNode *E =
+          FindNodeOrInsertPos(ID, dl, IP, ISD::EXPERIMENTAL_VECTOR_HISTOGRAM)) {
     cast<MaskedGatherSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -11414,7 +11433,7 @@ SDValue SelectionDAG::getMaskedHistogram(SDVTList VTs, EVT MemVT,
          "Scale should be a constant power of 2");
   assert(N->getInc().getValueType().isInteger() && "Non integer update value");
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11434,7 +11453,7 @@ SDValue SelectionDAG::getLoadFFVP(EVT VT, const SDLoc &DL, SDValue Chain,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
+  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP, ISD::VP_LOAD_FF)) {
     cast<VPLoadFFSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
@@ -11442,7 +11461,7 @@ SDValue SelectionDAG::getLoadFFVP(EVT VT, const SDLoc &DL, SDValue Chain,
                                       VT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11462,14 +11481,14 @@ SDValue SelectionDAG::getGetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::GET_FPENV_MEM))
     return SDValue(E, 0);
 
   auto *N = newSDNode<FPStateAccessSDNode>(ISD::GET_FPENV_MEM, dl.getIROrder(),
                                            dl.getDebugLoc(), VTs, MemVT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11489,14 +11508,14 @@ SDValue SelectionDAG::getSetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr,
   ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
   ID.AddInteger(MMO->getFlags());
   void *IP = nullptr;
-  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
+  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP, ISD::SET_FPENV_MEM))
     return SDValue(E, 0);
 
   auto *N = newSDNode<FPStateAccessSDNode>(ISD::SET_FPENV_MEM, dl.getIROrder(),
                                            dl.getDebugLoc(), VTs, MemVT, MMO);
   createOperands(N, Ops);
 
-  CSEMap.InsertNode(N, IP);
+  CSEMap->InsertNode(N, IP);
   InsertNode(N);
   SDValue V(N, 0);
   NewSDValueDbgMsg(V, "Creating new node: ", this);
@@ -11722,7 +11741,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     AddNodeIDNode(ID, Opcode, VTs, Ops);
     void *IP = nullptr;
 
-    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
+    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP, Opcode)) {
       E->intersectFlagsWith(Flags);
       return SDValue(E, 0);
     }
@@ -11730,7 +11749,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
     createOperands(N, Ops);
 
-    CSEMap.InsertNode(N, IP);
+    CSEMap->InsertNode(N, IP);
   } else {
     N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
     createOperands(N, Ops);
@@ -11918,14 +11937,14 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,
     FoldingSetNodeID ID;
     AddNodeIDNode(ID, Opcode, VTList, Ops);
     void *IP = nullptr;
-    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
+    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP, Opcode)) {
       E->intersectFlagsWith(Flags);
       return SDValue(E, 0);
     }
 
     N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTList);
     createOperands(N, Ops);
-    CSEMap.InsertNode(N, IP);
+    CSEMap->InsertNode(N, IP);
   } else {
     N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTList);
     createOperands(N, Ops);
@@ -12088,7 +12107,8 @@ SDNode *SelectionDAG::UpdateNodeOperands(SDNode *N, SDValue Op) {
 
   updateDivergence(N);
   // If this gets put into a CSE map, add it.
-  if (InsertPos) CSEMap.InsertNode(N, InsertPos);
+  if (InsertPos)
+    CSEMap->InsertNode(N, InsertPos);
   return N;
 }
 
@@ -12117,7 +12137,8 @@ SDNode *SelectionDAG::UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2) {
 
   updateDivergence(N);
   // If this gets put into a CSE map, add it.
-  if (InsertPos) CSEMap.InsertNode(N, InsertPos);
+  if (InsertPos)
+    CSEMap->InsertNode(N, InsertPos);
   return N;
 }
 
@@ -12168,7 +12189,8 @@ UpdateNodeOperands(SDNode *N, ArrayRef<SDValue> Ops) {
 
   updateDivergence(N);
   // If this gets put into a CSE map, add it.
-  if (InsertPos) CSEMap.InsertNode(N, InsertPos);
+  if (InsertPos)
+    CSEMap->InsertNode(N, InsertPos);
   return N;
 }
 
@@ -12321,7 +12343,7 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
   if (VTs.VTs[VTs.NumVTs-1] != MVT::Glue) {
     FoldingSetNodeID ID;
     AddNodeIDNode(ID, Opc, VTs, Ops);
-    if (SDNode *ON = FindNodeOrInsertPos(ID, SDLoc(N), IP))
+    if (SDNode *ON = FindNodeOrInsertPos(ID, SDLoc(N), IP, Opc))
       return UpdateSDLocOnMergeSDNode(ON, SDLoc(N));
   }
 
@@ -12363,7 +12385,7 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
   }
 
   if (IP)
-    CSEMap.InsertNode(N, IP);   // Memoize the new node.
+    CSEMap->InsertNode(N, IP); // Memoize the new node.
   return N;
 }
 
@@ -12514,7 +12536,7 @@ MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &DL,
     FoldingSetNodeID ID;
     AddNodeIDNode(ID, ~Opcode, VTs, Ops);
     IP = nullptr;
-    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
+    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP, ~Opcode)) {
       return cast<MachineSDNode>(UpdateSDLocOnMergeSDNode(E, DL));
     }
   }
@@ -12524,7 +12546,7 @@ MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &DL,
   createOperands(N, Ops);
 
   if (DoCSE)
-    CSEMap.InsertNode(N, IP);
+    CSEMap->InsertNode(N, IP);
 
   InsertNode(N);
   NewSDValueDbgMsg(SDValue(N, 0), "Creating new machine node: ", this);
@@ -12573,7 +12595,7 @@ SDNode *SelectionDAG::getNodeIfExists(unsigned Opcode, SDVTList VTList,
     FoldingSetNodeID ID;
     AddNodeIDNode(ID, Opcode, VTList, LookupOps);
     void *IP = nullptr;
-    if (SDNode *E = FindNodeOrInsertPos(ID, IP)) {
+    if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP, Opcode)) {
       E->intersectFlagsWith(Flags);
       return E;
     }
@@ -12596,7 +12618,7 @@ bool SelectionDAG::doesNodeExist(unsigned Opcode, SDVTList VTList,
     FoldingSetNodeID ID;
     AddNodeIDNode(ID, Opcode, VTList, Ops);
     void *IP = nullptr;
-    if (FindNodeOrInsertPos(ID, SDLoc(), IP))
+    if (FindNodeOrInsertPos(ID, SDLoc(), IP, Opcode))
       return true;
   }
   return false;
diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp
index a3c98aec98c81..b48df4166e09b 100644
--- a/llvm/lib/IR/DebugLoc.cpp
+++ b/llvm/lib/IR/DebugLoc.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/IR/DebugLoc.h"
+#include "llvm/ADT/FoldingSet.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/IR/DebugInfo.h"
 
@@ -93,6 +94,13 @@ void DebugLoc::setImplicitCode(bool ImplicitCode) {
     Loc->setImplicitCode(ImplicitCode);
 }
 
+void DebugLoc::Profile(FoldingSetNodeID &ID) const {
+  auto *Scope = cast<DIScope>(getScope());
+  ID.AddString(Scope->getFilename());
+  ID.AddInteger(getLine());
+  ID.AddInteger(getCol());
+}
+
 DebugLoc DebugLoc::replaceInlinedAtSubprogram(
     const DebugLoc &RootLoc, DISubprogram &NewSP, LLVMContext &Ctx,
     DenseMap<const MDNode *, MDNode *> &Cache) {
diff --git a/llvm/lib/Target/NVPTX/NVPTXSelectionDAGInfo.cpp b/llvm/lib/Target/NVPTX/NVPTXSelectionDAGInfo.cpp
index 710d063e75725..8f737e2e6d2f8 100644
--- a/llvm/lib/Target/NVPTX/NVPTXSelectionDAGInfo.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXSelectionDAGInfo.cpp
@@ -7,12 +7,90 @@
 //===----------------------------------------------------------------------===//
 
 #include "NVPTXSelectionDAGInfo.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/Support/CodeGen.h"
+#include <memory>
 
 #define GET_SDNODE_DESC
 #include "NVPTXGenSDNodeInfo.inc"
 
 using namespace llvm;
 
+// ---------------------------------------------------------------------------
+// DebugLoc-aware CSE map for NVPTX
+// ---------------------------------------------------------------------------
+
+/// Appends DebugLoc data to ID at -O0, so nodes at different source locations
+/// are not merged.  Constants are always CSE'd regardless of location.
+static void profileDebugLoc(FoldingSetNodeID &ID, unsigned Opcode,
+                            const DebugLoc &DL, const SelectionDAG &DAG) {
+  if (DAG.getOptLevel() != CodeGenOptLevel::None)
+    return;
+  if (!DL)
+    return;
+  switch (Opcode) {
+  case ISD::UNDEF:
+  case ISD::Constant:
+  case ISD::ConstantFP:
+  case ISD::TargetConstant:
+  case ISD::TargetConstantFP:
+    return; // Always CSE constants regardless of location.
+  default:
+    DL.Profile(ID);
+  }
+}
+
+/// Profile specialization: must key nodes identically to FindNodeOrInsertPos.
+namespace llvm {
+template <>
+struct ContextualFoldingSetTrait<SDNode, SelectionDAG *>
+    : public DefaultContextualFoldingSetTrait<SDNode, SelectionDAG *> {
+  static void Profile(SDNode &N, FoldingSetNodeID &ID, SelectionDAG *DAG) {
+    N.Profile(ID);
+    profileDebugLoc(ID, N.getOpcode(), N.getDebugLoc(), *DAG);
+  }
+};
+} // namespace llvm
+
+namespace {
+
+/// CSE map that at -O0 keys each node by both its DAG structure and its
+/// DebugLoc, so identical operations at different source lines stay distinct.
+class NVPTXSDNodeCSEMap final : public SDNodeCSEMap {
+  ContextualFoldingSet<SDNode, SelectionDAG *> FS;
+
+public:
+  explicit NVPTXSDNodeCSEMap(SelectionDAG *DAG) : FS(DAG) {}
+
+  SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, unsigned Opcode,
+                              const SDLoc &DL, void *&InsertPos) override {
+    FoldingSetNodeID AugID = ID;
+    profileDebugLoc(AugID, Opcode, DL.getDebugLoc(), *FS.getContext());
+    return FS.FindNodeOrInsertPos(AugID, InsertPos);
+  }
+
+  void InsertNode(SDNode *N, void *InsertPos) override {
+    FS.InsertNode(N, InsertPos);
+  }
+
+  bool RemoveNode(SDNode *N) override { return FS.RemoveNode(N); }
+
+  SDNode *GetOrInsertNode(SDNode *N) override { return FS.GetOrInsertNode(N); }
+
+  void clear() override { FS.clear(); }
+};
+
+} // namespace
+
+std::unique_ptr<SDNodeCSEMap>
+NVPTXSelectionDAGInfo::createCSEMap(SelectionDAG &DAG) const {
+  return std::make_unique<NVPTXSDNodeCSEMap>(&DAG);
+}
+
 NVPTXSelectionDAGInfo::NVPTXSelectionDAGInfo()
     : SelectionDAGGenTargetInfo(NVPTXGenSDNodeInfo) {}
 
diff --git a/llvm/lib/Target/NVPTX/NVPTXSelectionDAGInfo.h b/llvm/lib/Target/NVPTX/NVPTXSelectionDAGInfo.h
index 9dd0a1eaa5856..993dda10c8a2e 100644
--- a/llvm/lib/Target/NVPTX/NVPTXSelectionDAGInfo.h
+++ b/llvm/lib/Target/NVPTX/NVPTXSelectionDAGInfo.h
@@ -59,6 +59,8 @@ class NVPTXSelectionDAGInfo : public SelectionDAGGenTargetInfo {
 
   void verifyTargetNode(const SelectionDAG &DAG,
                         const SDNode *N) const override;
+
+  std::unique_ptr<SDNodeCSEMap> createCSEMap(SelectionDAG &DAG) const override;
 };
 
 } // namespace llvm

>From 4ef04c354f9e27cddb9963f886d6c13ee65c6156 Mon Sep 17 00:00:00 2001
From: Princeton Ferro <pferro at nvidia.com>
Date: Sat, 18 Apr 2026 15:45:26 -0700
Subject: [PATCH 2/2] [SelectionDAG][NVPTX] Add lit tests for DebugLoc-aware
 CSE

Verify that NVPTXSDNodeCSEMap correctly keys CSE by DebugLoc at -O0:

- no-cse-diff-loc.ll: identical operations at different source lines must
  not be folded into one instruction.
- cse-same-loc.ll: identical operations at the same source line must still
  be CSE'd; the consumer sees the same register for both operands.
- cse-opt.ll: at -O1 and above, DebugLoc is not part of the key, so
  operations at different source lines are folded normally.
- cse-constants.ll: ISD::Constant nodes are excluded from DebugLoc keying,
  so identical constant SDNodes are always shared; operations with
  constant operands then follow the normal DebugLoc-keyed rule (same loc
  folds, different loc does not).

Co-Authored-By: Claude Sonnet 4.6 <noreply at anthropic.com>
---
 llvm/test/DebugInfo/NVPTX/cse-constants.ll   | 63 ++++++++++++++++++++
 llvm/test/DebugInfo/NVPTX/cse-opt.ll         | 34 +++++++++++
 llvm/test/DebugInfo/NVPTX/cse-same-loc.ll    | 33 ++++++++++
 llvm/test/DebugInfo/NVPTX/no-cse-diff-loc.ll | 32 ++++++++++
 4 files changed, 162 insertions(+)
 create mode 100644 llvm/test/DebugInfo/NVPTX/cse-constants.ll
 create mode 100644 llvm/test/DebugInfo/NVPTX/cse-opt.ll
 create mode 100644 llvm/test/DebugInfo/NVPTX/cse-same-loc.ll
 create mode 100644 llvm/test/DebugInfo/NVPTX/no-cse-diff-loc.ll

diff --git a/llvm/test/DebugInfo/NVPTX/cse-constants.ll b/llvm/test/DebugInfo/NVPTX/cse-constants.ll
new file mode 100644
index 0000000000000..d6d05d08b00e0
--- /dev/null
+++ b/llvm/test/DebugInfo/NVPTX/cse-constants.ll
@@ -0,0 +1,63 @@
+; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda -O0 | FileCheck %s
+; RUN: %if ptxas %{ llc < %s -mtriple=nvptx64-nvidia-cuda -O0 | %ptxas-verify %}
+
+; At -O0, NVPTXSDNodeCSEMap excludes ISD::Constant from DebugLoc keying, so
+; identical constant SDNodes are always shared regardless of source location.
+; Operations with constant operands therefore inherit the normal DebugLoc-keyed
+; behavior: same DebugLoc folds, different DebugLoc does not.
+;
+; The volatile stores keep DAGCombine from folding (a+c) + (a+c) into 2a+2c,
+; which would obscure the per-line DebugLoc structure we want to verify.
+
+; -- Same DebugLoc: identical operations sharing a constant operand must be
+;    folded into one instruction; both volatile stores must source the same
+;    register.
+define void @const_same_loc(i32 %a, ptr %p1, ptr %p2) !dbg !3 {
+; CHECK-LABEL: const_same_loc(
+; CHECK:     .loc {{[0-9]+}} 1
+; CHECK:     add.s32 [[REG:%r[0-9]+]],
+; CHECK-NOT: add.s32
+; CHECK:     st.volatile.b32 {{.*}}, [[REG]];
+; CHECK:     st.volatile.b32 {{.*}}, [[REG]];
+  %x = add i32 %a, 42, !dbg !6
+  %y = add i32 %a, 42, !dbg !6
+  store volatile i32 %x, ptr %p1, !dbg !8
+  store volatile i32 %y, ptr %p2, !dbg !9
+  ret void, !dbg !10
+}
+
+; -- Different DebugLoc: identical operations sharing a constant operand must
+;    each produce their own .loc and instruction, even though the constant
+;    operand 42 is one shared SDNode.
+define void @const_diff_loc(i32 %a, ptr %p1, ptr %p2) !dbg !20 {
+; CHECK-LABEL: const_diff_loc(
+; CHECK: .loc {{[0-9]+}} 1
+; CHECK: add.s32
+; CHECK: .loc {{[0-9]+}} 2
+; CHECK: add.s32
+  %x = add i32 %a, 42, !dbg !21
+  %y = add i32 %a, 42, !dbg !22
+  store volatile i32 %x, ptr %p1, !dbg !23
+  store volatile i32 %y, ptr %p2, !dbg !24
+  ret void, !dbg !25
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "test.cu", directory: "/")
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = distinct !DISubprogram(name: "const_same_loc", scope: !1, file: !1, line: 1, type: !4, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5)
+!4 = !DISubroutineType(types: !5)
+!5 = !{}
+!6 = !DILocation(line: 1, column: 1, scope: !3)
+!8 = !DILocation(line: 3, column: 1, scope: !3)
+!9 = !DILocation(line: 4, column: 1, scope: !3)
+!10 = !DILocation(line: 5, column: 1, scope: !3)
+!20 = distinct !DISubprogram(name: "const_diff_loc", scope: !1, file: !1, line: 1, type: !4, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5)
+!21 = !DILocation(line: 1, column: 1, scope: !20)
+!22 = !DILocation(line: 2, column: 1, scope: !20)
+!23 = !DILocation(line: 3, column: 1, scope: !20)
+!24 = !DILocation(line: 4, column: 1, scope: !20)
+!25 = !DILocation(line: 5, column: 1, scope: !20)
diff --git a/llvm/test/DebugInfo/NVPTX/cse-opt.ll b/llvm/test/DebugInfo/NVPTX/cse-opt.ll
new file mode 100644
index 0000000000000..345fff18b76df
--- /dev/null
+++ b/llvm/test/DebugInfo/NVPTX/cse-opt.ll
@@ -0,0 +1,34 @@
+; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda -O1 | FileCheck %s
+; RUN: %if ptxas %{ llc < %s -mtriple=nvptx64-nvidia-cuda -O1 | %ptxas-verify %}
+
+; At -O1 and above, NVPTXSDNodeCSEMap does not include DebugLoc in the key, so
+; identical operations at different source locations are folded normally.  The
+; source location from the second operation (line 2) must not appear in the
+; output, and the consumer must see the same register for both operands.
+
+define i32 @cse_opt(i32 %a, i32 %b) !dbg !3 {
+; CHECK-LABEL: cse_opt(
+; CHECK:     .loc {{[0-9]+}} 1
+; CHECK:     add.s32 [[REG:%r[0-9]+]],
+; CHECK-NOT: .loc {{[0-9]+}} 2
+; CHECK:     .loc {{[0-9]+}} 3
+; CHECK:     add.s32 {{%r[0-9]+}}, [[REG]], [[REG]]
+  %x = add i32 %a, %b, !dbg !6
+  %y = add i32 %a, %b, !dbg !7
+  %z = add i32 %x, %y, !dbg !8
+  ret i32 %z, !dbg !9
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "test.cu", directory: "/")
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = distinct !DISubprogram(name: "cse_opt", scope: !1, file: !1, line: 1, type: !4, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5)
+!4 = !DISubroutineType(types: !5)
+!5 = !{}
+!6 = !DILocation(line: 1, column: 1, scope: !3)
+!7 = !DILocation(line: 2, column: 1, scope: !3)
+!8 = !DILocation(line: 3, column: 1, scope: !3)
+!9 = !DILocation(line: 4, column: 1, scope: !3)
diff --git a/llvm/test/DebugInfo/NVPTX/cse-same-loc.ll b/llvm/test/DebugInfo/NVPTX/cse-same-loc.ll
new file mode 100644
index 0000000000000..13a36e41c0407
--- /dev/null
+++ b/llvm/test/DebugInfo/NVPTX/cse-same-loc.ll
@@ -0,0 +1,33 @@
+; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda -O0 | FileCheck %s
+; RUN: %if ptxas %{ llc < %s -mtriple=nvptx64-nvidia-cuda -O0 | %ptxas-verify %}
+
+; At -O0, NVPTX keys CSE by both DAG structure and DebugLoc.  Two identical
+; operations at the SAME source location must be folded into one instruction;
+; the consumer of both results must therefore see the same register for both
+; operands.
+
+define i32 @cse_same_loc(i32 %a, i32 %b) !dbg !3 {
+; CHECK-LABEL: cse_same_loc(
+; CHECK:     .loc {{[0-9]+}} 1
+; CHECK:     add.s32 [[REG:%r[0-9]+]],
+; CHECK-NOT: .loc {{[0-9]+}} 1
+; CHECK:     .loc {{[0-9]+}} 3
+; CHECK:     add.s32 {{%r[0-9]+}}, [[REG]], [[REG]]
+  %x = add i32 %a, %b, !dbg !6
+  %y = add i32 %a, %b, !dbg !6
+  %z = add i32 %x, %y, !dbg !8
+  ret i32 %z, !dbg !9
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "test.cu", directory: "/")
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = distinct !DISubprogram(name: "cse_same_loc", scope: !1, file: !1, line: 1, type: !4, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5)
+!4 = !DISubroutineType(types: !5)
+!5 = !{}
+!6 = !DILocation(line: 1, column: 1, scope: !3)
+!8 = !DILocation(line: 3, column: 1, scope: !3)
+!9 = !DILocation(line: 4, column: 1, scope: !3)
diff --git a/llvm/test/DebugInfo/NVPTX/no-cse-diff-loc.ll b/llvm/test/DebugInfo/NVPTX/no-cse-diff-loc.ll
new file mode 100644
index 0000000000000..b600433a2a729
--- /dev/null
+++ b/llvm/test/DebugInfo/NVPTX/no-cse-diff-loc.ll
@@ -0,0 +1,32 @@
+; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda -O0 | FileCheck %s
+; RUN: %if ptxas %{ llc < %s -mtriple=nvptx64-nvidia-cuda -O0 | %ptxas-verify %}
+
+; At -O0, NVPTX keys CSE by both DAG structure and DebugLoc.  Two identical
+; operations at different source lines must each produce their own .loc entry
+; and instruction rather than being folded into one.
+
+define i32 @no_cse_diff_loc(i32 %a, i32 %b) !dbg !3 {
+; CHECK-LABEL: no_cse_diff_loc(
+; CHECK: .loc {{[0-9]+}} 1
+; CHECK: add.s32
+; CHECK: .loc {{[0-9]+}} 2
+; CHECK: add.s32
+  %x = add i32 %a, %b, !dbg !6
+  %y = add i32 %a, %b, !dbg !7
+  %z = add i32 %x, %y, !dbg !8
+  ret i32 %z, !dbg !9
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "test.cu", directory: "/")
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = distinct !DISubprogram(name: "no_cse_diff_loc", scope: !1, file: !1, line: 1, type: !4, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5)
+!4 = !DISubroutineType(types: !5)
+!5 = !{}
+!6 = !DILocation(line: 1, column: 1, scope: !3)
+!7 = !DILocation(line: 2, column: 1, scope: !3)
+!8 = !DILocation(line: 3, column: 1, scope: !3)
+!9 = !DILocation(line: 4, column: 1, scope: !3)



More information about the llvm-commits mailing list