diff options
| author | Yong He <yonghe@outlook.com> | 2022-02-25 20:49:31 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-02-25 20:49:31 -0800 |
| commit | c31577953d5041c82375c22d847c2eba06106c58 (patch) | |
| tree | bc685a8b63fc13cb85d160ae13df950056ca6e91 /source/slang/slang-ir-simplify-cfg.cpp | |
| parent | 8990d270e3a0c01b1f7abbf4f79556c5ef82a096 (diff) | |
Improved SCCP, inlining and resource specialization passes, legalize `ImageSubscript` for GLSL (#2146)
Diffstat (limited to 'source/slang/slang-ir-simplify-cfg.cpp')
| -rw-r--r-- | source/slang/slang-ir-simplify-cfg.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/source/slang/slang-ir-simplify-cfg.cpp b/source/slang/slang-ir-simplify-cfg.cpp new file mode 100644 index 000000000..af0e7c0ce --- /dev/null +++ b/source/slang/slang-ir-simplify-cfg.cpp @@ -0,0 +1,82 @@ +#include "slang-ir-simplify-cfg.h" + +#include "slang-ir-insts.h" +#include "slang-ir.h" + +namespace Slang +{ + +bool processFunc(IRFunc* func) +{ + auto firstBlock = func->getFirstBlock(); + if (!firstBlock) + return false; + + bool changed = false; + + List<IRBlock*> workList; + HashSet<IRBlock*> processedBlock; + workList.add(func->getFirstBlock()); + while (workList.getCount()) + { + auto block = workList.getFirst(); + workList.fastRemoveAt(0); + while (block) + { + // If `block` does not end with an unconditional branch, bail. + if (block->getTerminator()->getOp() != kIROp_unconditionalBranch) + break; + auto branch = as<IRUnconditionalBranch>(block->getTerminator()); + auto successor = branch->getTargetBlock(); + // Only perform the merge if `block` is the only predecessor of `successor`. + // We also need to make sure not to merge a block that serves as the + // merge point in CFG. Such blocks will have more than one use. + if (successor->hasMoreThanOneUse()) + break; + changed = true; + Index paramIndex = 0; + auto inst = successor->getFirstDecorationOrChild(); + while (inst) + { + auto next = inst->getNextInst(); + if (inst->getOp() == kIROp_Param) + { + inst->replaceUsesWith(branch->getArg(paramIndex)); + paramIndex++; + } + else + { + inst->removeFromParent(); + inst->insertAtEnd(block); + } + inst = next; + } + branch->removeAndDeallocate(); + assert(!successor->hasUses()); + successor->removeAndDeallocate(); + } + for (auto successor : block->getSuccessors()) + { + if (processedBlock.Add(successor)) + { + workList.add(successor); + } + } + } + return changed; +} + +bool simplifyCFG(IRModule* module) +{ + bool changed = false; + for (auto inst : module->getGlobalInsts()) + { + if (auto func = as<IRFunc>(inst)) + { + changed |= processFunc(func); + } + } + return changed; +} + +} // namespace Slang |
