summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-undo-param-copy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-ir-undo-param-copy.cpp')
-rw-r--r--source/slang/slang-ir-undo-param-copy.cpp141
1 files changed, 141 insertions, 0 deletions
diff --git a/source/slang/slang-ir-undo-param-copy.cpp b/source/slang/slang-ir-undo-param-copy.cpp
new file mode 100644
index 000000000..d8aac7201
--- /dev/null
+++ b/source/slang/slang-ir-undo-param-copy.cpp
@@ -0,0 +1,141 @@
+#include "slang-ir-undo-param-copy.h"
+
+#include "slang-ir-dce.h"
+#include "slang-ir-insts.h"
+#include "slang-ir.h"
+
+namespace Slang
+{
+// This pass transforms variables decorated with TempCallArgVarDecoration
+// by replacing them with direct references to the original parameters.
+// This is important for CUDA/OptiX targets where functions like 'IgnoreHit'
+// can prevent copy-back operations from executing.
+struct UndoParameterCopyVisitor
+{
+ IRBuilder builder;
+ IRModule* module;
+ bool changed = false;
+
+ // Track instructions to remove
+ List<IRInst*> instsToRemove;
+
+ UndoParameterCopyVisitor(IRModule* module)
+ : module(module)
+ {
+ builder.setInsertInto(module);
+ }
+
+ // Process the entire module
+ void processModule()
+ {
+ // Process all functions in the module
+ for (auto inst = module->getModuleInst()->getFirstChild(); inst; inst = inst->getNextInst())
+ {
+ if (auto func = as<IRFunc>(inst))
+ {
+ processFunc(func);
+ }
+ }
+ }
+
+ // Process a single function
+ void processFunc(IRFunc* func)
+ {
+ instsToRemove.clear();
+ HashSet<IRInst*> originalPtrsForCopyBackCandidates; // Tracks original params that might
+ // have a redundant copy-back
+
+ // Single pass to identify temps, replace uses, and identify redundant copy-back stores.
+ for (auto block = func->getFirstBlock(); block; block = block->getNextBlock())
+ {
+ for (auto inst = block->getFirstInst(); inst; inst = inst->getNextInst())
+ {
+ if (auto varInst = as<IRVar>(inst))
+ {
+ if (varInst->findDecoration<IRTempCallArgVarDecoration>())
+ {
+ IRStore* initializingStore = nullptr;
+ IRInst* originalParamPtr = nullptr;
+
+ // Scan for the store that initializes this varInst
+ // This store should be in the same block, after varInst.
+ // The value stored should be an IRLoad from the original parameter pointer.
+ for (auto scanInst = varInst->getNextInst(); scanInst;
+ scanInst = scanInst->getNextInst())
+ {
+ if (auto storeInst = as<IRStore>(scanInst))
+ {
+ if (storeInst->getPtr() == varInst)
+ {
+ initializingStore = storeInst;
+ if (auto loadInst = as<IRLoad>(storeInst->getVal()))
+ {
+ originalParamPtr = loadInst->getPtr();
+
+ // Found the pattern: var, store(var, load(originalParam))
+ this->changed = true;
+
+ // Replace uses of varInst with originalParamPtr immediately
+ varInst->replaceUsesWith(originalParamPtr);
+
+ // Mark for removal
+ instsToRemove.add(initializingStore);
+ instsToRemove.add(varInst);
+
+ // Record originalParamPtr for copy-back optimization check
+ originalPtrsForCopyBackCandidates.add(originalParamPtr);
+ }
+ break; // Found the initializing store for varInst
+ }
+ }
+ // Stop scanning if another var declaration or a call is encountered
+ if (as<IRVar>(scanInst) || as<IRCall>(scanInst))
+ {
+ break;
+ }
+ }
+ }
+ }
+ else if (auto storeInst = as<IRStore>(inst))
+ {
+ // Check for redundant copy-back: store(originalParam, load(originalParam))
+ IRInst* destPtr = storeInst->getPtr();
+ if (originalPtrsForCopyBackCandidates.contains(destPtr))
+ {
+ if (auto loadVal = as<IRLoad>(storeInst->getVal()))
+ {
+ if (loadVal->getPtr() == destPtr)
+ {
+ // This is a redundant copy-back store
+ instsToRemove.add(storeInst);
+ this->changed = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Removal pass
+ for (auto& inst : instsToRemove)
+ {
+ if (inst->getParent())
+ {
+ inst->removeAndDeallocate();
+ }
+ }
+ }
+};
+
+void undoParameterCopy(IRModule* module)
+{
+ UndoParameterCopyVisitor visitor(module);
+ visitor.processModule();
+
+ // Run DCE to clean up any dead instructions
+ if (visitor.changed)
+ {
+ eliminateDeadCode(module);
+ }
+}
+} // namespace Slang