From bd6306cdaa4a49344658bd026721b6532e103d09 Mon Sep 17 00:00:00 2001 From: Yong He Date: Fri, 24 Feb 2023 10:01:47 -0800 Subject: More control flow simplifications. (#2673) * More control flow and Phi param simplifications. * Fix. * Fix gcc error. * Fix. * More IR cleanup. * Fix bug in phi param dce + ifelse simplify. * Propagate and DCE side-effect-free functions. * Enhance CFG simplifcation to remove loops with no side effects. * Fix. * Fixes. * Fix tests. Add [__AlwaysFoldIntoUseSite] for rayPayloadLocation. * More cleanup. * Fixes. * Fix. --------- Co-authored-by: Yong He --- .../slang/slang-ir-propagate-func-properties.cpp | 186 +++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 source/slang/slang-ir-propagate-func-properties.cpp (limited to 'source/slang/slang-ir-propagate-func-properties.cpp') diff --git a/source/slang/slang-ir-propagate-func-properties.cpp b/source/slang/slang-ir-propagate-func-properties.cpp new file mode 100644 index 000000000..f98a77fc7 --- /dev/null +++ b/source/slang/slang-ir-propagate-func-properties.cpp @@ -0,0 +1,186 @@ +#include "slang-ir-propagate-func-properties.h" + +#include "slang-ir.h" +#include "slang-ir-insts.h" +#include "slang-ir-util.h" + + +namespace Slang +{ +bool propagateFuncProperties(IRModule* module) +{ + bool result = false; + List workList; + HashSet workListSet; + + auto addToWorkList = [&](IRFunc* f) + { + if (workListSet.Add(f)) + workList.add(f); + }; + auto addCallersToWorkList = [&](IRFunc* f) + { + if (auto g = findOuterGeneric(f)) + { + for (auto use = g->firstUse; use; use = use->nextUse) + { + if (use->getUser()->getOp() == kIROp_Specialize) + { + auto specialize = use->getUser(); + for (auto iuse = specialize->firstUse; iuse; iuse = iuse->nextUse) + { + if (auto userFunc = getParentFunc(iuse->getUser())) + addToWorkList(userFunc); + } + } + } + return; + } + for (auto use = f->firstUse; use; use = use->nextUse) + { + if (use->getUser()->getOp() == kIROp_Call) + { + if (auto userFunc = getParentFunc(use->getUser())) + addToWorkList(userFunc); + } + } + }; + for (;;) + { + bool changed = false; + workList.clear(); + workListSet.Clear(); + + // Add side effect free functions and their transitive callers to work list. + for (auto inst : module->getGlobalInsts()) + { + auto genericInst = as(inst); + if (genericInst) + { + inst = findGenericReturnVal(genericInst); + } + if (auto func = as(inst)) + { + if (func->findDecoration()) + { + addCallersToWorkList(func); + } + } + } + + // Add remaining functions to work list. + for (auto inst : module->getGlobalInsts()) + { + auto genericInst = as(inst); + if (genericInst) + { + inst = findGenericReturnVal(genericInst); + } + if (auto func = as(inst)) + { + addToWorkList(func); + } + } + + IRBuilder builder(module); + + for (Index i = 0; i < workList.getCount(); i++) + { + auto f = workList[i]; + bool hasSideEffectCall = false; + if (f->findDecoration()) + continue; + // Never propagate to functions without a body. + if (f->getFirstBlock() == nullptr) + continue; + if (f->findDecoration()) + continue; + for (auto block : f->getBlocks()) + { + for (auto inst : block->getChildren()) + { + // Is this inst known to not have global side effect/analyzable? + if (inst->mightHaveSideEffects()) + { + switch (inst->getOp()) + { + case kIROp_ifElse: + case kIROp_unconditionalBranch: + case kIROp_Switch: + case kIROp_Return: + case kIROp_loop: + case kIROp_Store: + case kIROp_Call: + case kIROp_Param: + case kIROp_Unreachable: + break; + default: + // We have a inst that has side effect and is not understood by this method. + // e.g. bufferStore, discard, etc. + return true; + } + } + + if (auto call = as(inst)) + { + auto callee = getResolvedInstForDecorations(call->getCallee()); + switch (callee->getOp()) + { + default: + // We are calling an unknown function, so we have to assume + // there are side effects in the call. + hasSideEffectCall = true; + break; + case kIROp_Func: + if (!callee->findDecoration()) + { + hasSideEffectCall = true; + break; + } + } + } + + // Are any operands defined in global scope? + for (UInt o = 0; o < inst->getOperandCount(); o++) + { + auto operand = inst->getOperand(o); + if (getParentFunc(operand) == f) + continue; + if (as(operand)) + continue; + if (as(operand)) + continue; + switch (operand->getOp()) + { + case kIROp_Specialize: + case kIROp_LookupWitness: + case kIROp_StructKey: + case kIROp_WitnessTable: + case kIROp_WitnessTableEntry: + case kIROp_undefined: + case kIROp_Func: + continue; + default: + break; + } + hasSideEffectCall = true; + break; + } + } + if (hasSideEffectCall) + break; + } + if (!hasSideEffectCall) + { + builder.addDecoration(f, kIROp_ReadNoneDecoration); + addCallersToWorkList(f); + changed = true; + } + } + result |= changed; + if (!changed) + break; + } + return result; +} +} -- cgit v1.2.3