summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-hoist-constants.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-ir-hoist-constants.cpp')
-rw-r--r--source/slang/slang-ir-hoist-constants.cpp96
1 files changed, 96 insertions, 0 deletions
diff --git a/source/slang/slang-ir-hoist-constants.cpp b/source/slang/slang-ir-hoist-constants.cpp
new file mode 100644
index 000000000..87d3487a3
--- /dev/null
+++ b/source/slang/slang-ir-hoist-constants.cpp
@@ -0,0 +1,96 @@
+// slang-ir-hoist-constants.cpp
+#include "slang-ir-hoist-constants.h"
+#include "slang-ir-inst-pass-base.h"
+
+namespace Slang
+{
+
+struct HoistConstantPass : InstPassBase
+{
+ HoistConstantPass(IRModule* module) : InstPassBase(module)
+ {}
+
+ bool changed = false;
+
+ void processModule()
+ {
+ sharedBuilderStorage.init(module);
+
+ processAllInsts([this](IRInst* inst)
+ {
+
+ if (inst->getParent() == module->getModuleInst() || !inst->getParent())
+ return;
+ auto parent = inst->getParent();
+ auto p = parent;
+ while (p)
+ {
+ if (as<IRGlobalValueWithCode>(p))
+ return;
+ p = p->parent;
+ }
+ while (parent && parent->parent != module->getModuleInst())
+ parent = parent->parent;
+ if (!parent)
+ return;
+ switch (inst->getOp())
+ {
+ default:
+ return;
+ case kIROp_Add:
+ case kIROp_Sub:
+ case kIROp_Mul:
+ case kIROp_Div:
+ case kIROp_Module:
+ case kIROp_Neg:
+ case kIROp_And:
+ case kIROp_Or:
+ case kIROp_Not:
+ case kIROp_BitAnd:
+ case kIROp_BitNot:
+ case kIROp_BitOr:
+ case kIROp_BitXor:
+ case kIROp_Select:
+ case kIROp_Greater:
+ case kIROp_Less:
+ case kIROp_Leq:
+ case kIROp_Geq:
+ case kIROp_Eql:
+ case kIROp_Neq:
+ case kIROp_BitCast:
+ case kIROp_Lsh:
+ case kIROp_Rsh:
+ case kIROp_Construct:
+ case kIROp_makeVector:
+ case kIROp_MakeMatrix:
+ case kIROp_swizzle:
+ case kIROp_IntLit:
+ case kIROp_BoolLit:
+ case kIROp_ArrayType:
+ case kIROp_Specialize:
+ case kIROp_VectorType:
+ break;
+ }
+ if (inst->typeUse.get() && inst->typeUse.get()->parent != module->getModuleInst())
+ return;
+ for (UInt i = 0; i < inst->getOperandCount(); i++)
+ {
+ if (inst->getOperand(i)->parent != module->getModuleInst())
+ return;
+ }
+ // all operands are in global scope, we can move this inst to global scope as well.
+ inst->insertBefore(parent);
+ changed = true;
+ });
+ }
+};
+
+bool hoistConstants(
+ IRModule* module)
+{
+ HoistConstantPass context(module);
+ context.processModule();
+ return context.changed;
+}
+
+}