[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