From: Dejan Mircevski Date: Tue, 19 Jan 2016 15:01:27 +0000 (-0500) Subject: Rework inReadableOrder() as a recursive descent. X-Git-Tag: upstream/0.1~293^2~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=38d039d0637a20c01f55645c3961a564d9f29e3f;p=platform%2Fupstream%2Fglslang.git Rework inReadableOrder() as a recursive descent. Add a test for unreachable merge block. Update test results with the new order: mainly delaying merge blocks and removing unreachable ones. --- diff --git a/SPIRV/InReadableOrder.cpp b/SPIRV/InReadableOrder.cpp index b24d3ef..de506f4 100644 --- a/SPIRV/InReadableOrder.cpp +++ b/SPIRV/InReadableOrder.cpp @@ -17,53 +17,52 @@ #include "spvIR.h" #include +#include #include #include -#include using spv::Block; using spv::Id; -using BlockSet = std::unordered_set; -using IdToBool = std::unordered_map; namespace { -// True if any of prerequisites have not yet been visited. May add new, -// zero-initialized, values to visited, but doesn't modify any existing values. -bool delay(const BlockSet& prereqs, IdToBool& visited) { - return std::any_of(prereqs.begin(), prereqs.end(), - [&visited](Id b) { return !visited[b]; }); -} -} +// Traverses CFG in a readable order, invoking a pre-set callback on each block. +// Use by calling visit() on the root block. +class ReadableOrderTraverser { + public: + explicit ReadableOrderTraverser(std::function callback) + : callback_(callback) {} -void spv::inReadableOrder(Block* root, std::function callback) { - // Prerequisites for a merge block; must be completed prior to visiting the - // merge block. - std::unordered_map prereqs; - IdToBool visited; // Whether a block has already been visited. - std::deque worklist; // DFS worklist - worklist.push_back(root); - while (!worklist.empty()) { - Block* current = worklist.front(); - worklist.pop_front(); - // Nodes may be pushed repeadetly (before they're first visited) if they - // have multiple predecessors. Skip the already-visited ones. - if (visited[current->getId()]) continue; - if (delay(prereqs[current->getId()], visited)) { - // Not every prerequisite has been visited -- push it off for later. - worklist.push_back(current); - continue; - } - callback(current); - visited[current->getId()] = true; - if (auto merge = current->getMergeInstruction()) { - Id mergeId = merge->getIdOperand(0); - auto& mergePrereqs = prereqs[mergeId]; - // Delay visiting merge blocks until all branches are visited. - for (const auto succ : current->getSuccessors()) - if (succ->getId() != mergeId) mergePrereqs.insert(succ->getId()); + // Visits the block if it hasn't been visited already and isn't currently + // being delayed. Invokes callback(block), then descends into its successors. + // Delays merge-block processing until all the branches have been completed. + void visit(Block* block) { + assert(block); + if (visited_[block] || delayed_[block]) return; + callback_(block); + visited_[block] = true; + Block* mergeBlock = nullptr; + auto mergeInst = block->getMergeInstruction(); + if (mergeInst) { + Id mergeId = mergeInst->getIdOperand(0); + mergeBlock = + block->getParent().getParent().getInstruction(mergeId)->getBlock(); + delayed_[mergeBlock] = true; } - for (auto succ : current->getSuccessors()) { - if (!visited[succ->getId()]) worklist.push_back(succ); + for (const auto succ : block->getSuccessors()) + if (succ != mergeBlock) visit(succ); + if (mergeBlock) { + delayed_[mergeBlock] = false; + visit(mergeBlock); } } + + private: + std::function callback_; + // Whether a block has already been visited or is being delayed. + std::unordered_map visited_, delayed_; +}; +} + +void spv::inReadableOrder(Block* root, std::function callback) { + ReadableOrderTraverser(callback).visit(root); } diff --git a/SPIRV/spvIR.h b/SPIRV/spvIR.h index a854384..307711b 100755 --- a/SPIRV/spvIR.h +++ b/SPIRV/spvIR.h @@ -60,6 +60,7 @@ namespace spv { +class Block; class Function; class Module; @@ -108,6 +109,8 @@ public: addImmediateOperand(word); } } + void setBlock(Block* b) { block = b; } + Block* getBlock() { return block; } Op getOpCode() const { return opCode; } int getNumOperands() const { return (int)operands.size(); } Id getResultId() const { return resultId; } @@ -146,6 +149,7 @@ protected: Op opCode; std::vector operands; std::string originalString; // could be optimized away; convenience for getting string operand + Block* block; }; // @@ -165,8 +169,8 @@ public: void addInstruction(std::unique_ptr inst); void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } - const std::vector getPredecessors() const { return predecessors; } - const std::vector getSuccessors() const { return successors; } + const std::vector& getPredecessors() const { return predecessors; } + const std::vector& getSuccessors() const { return successors; } void setUnreachable() { unreachable = true; } bool isUnreachable() const { return unreachable; } // Returns the block's merge instruction, if one exists (otherwise null). @@ -370,12 +374,15 @@ __inline void Function::addLocalVariable(std::unique_ptr inst) __inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) { instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); + instructions.back()->setBlock(this); + parent.getParent().mapInstruction(instructions.back()); } __inline void Block::addInstruction(std::unique_ptr inst) { - Instruction* raw_instruction = inst.get(); + Instruction* raw_instruction = inst.get(); instructions.push_back(std::move(inst)); + raw_instruction->setBlock(this); if (raw_instruction->getResultId()) parent.getParent().mapInstruction(raw_instruction); } diff --git a/Test/baseResults/spv.always-discard.frag.out b/Test/baseResults/spv.always-discard.frag.out old mode 100755 new mode 100644 index a639515..73e34bd --- a/Test/baseResults/spv.always-discard.frag.out +++ b/Test/baseResults/spv.always-discard.frag.out @@ -110,23 +110,4 @@ Linked fragment stage: Branch 49 49: Label Kill - 69: Label - 70: 6(float) Load 36(radius) - 72: 46(bool) FOrdGreaterThanEqual 70 71 - SelectionMerge 74 None - BranchConditional 72 73 74 - 73: Label - 75: 6(float) Load 36(radius) - 77: 6(float) ExtInst 1(GLSL.std.450) 26(Pow) 75 76 - 78: 6(float) FDiv 77 27 - 79: 6(float) ExtInst 1(GLSL.std.450) 4(FAbs) 78 - 80: 7(fvec4) Load 15(color) - 81: 7(fvec4) CompositeConstruct 79 79 79 79 - 82: 7(fvec4) FSub 80 81 - Store 15(color) 82 - Branch 74 - 74: Label - 83: 7(fvec4) Load 15(color) - Store 59(gl_FragColor) 83 - Return FunctionEnd diff --git a/Test/baseResults/spv.do-while-continue-break.vert.out b/Test/baseResults/spv.do-while-continue-break.vert.out old mode 100755 new mode 100644 index c483861..44a1730 --- a/Test/baseResults/spv.do-while-continue-break.vert.out +++ b/Test/baseResults/spv.do-while-continue-break.vert.out @@ -81,9 +81,6 @@ Linked vertex stage: 28: Label Store 30(B) 19 Branch 10 - 32: Label - Store 33(C) 26 - Branch 29 29: Label 34: 6(int) Load 8(i) 36: 14(bool) IEqual 34 35 @@ -92,9 +89,6 @@ Linked vertex stage: 37: Label Store 39(D) 40 Branch 11 - 41: Label - Store 42(E) 43 - Branch 38 38: Label Store 44(F) 45 Branch 10 diff --git a/Test/baseResults/spv.for-continue-break.vert.out b/Test/baseResults/spv.for-continue-break.vert.out old mode 100755 new mode 100644 index 92976eb..c759fc6 --- a/Test/baseResults/spv.for-continue-break.vert.out +++ b/Test/baseResults/spv.for-continue-break.vert.out @@ -70,9 +70,6 @@ Linked vertex stage: 27: 6(int) IAdd 26 18 Store 8(i) 27 Branch 10 - 28: Label - Store 29(C) 18 - Branch 24 24: Label 30: 6(int) Load 8(i) 32: 6(int) SMod 30 31 @@ -82,9 +79,6 @@ Linked vertex stage: 34: Label Store 36(D) 18 Branch 11 - 37: Label - Store 38(E) 18 - Branch 35 35: Label Store 39(F) 40 41: 6(int) Load 8(i) diff --git a/Test/baseResults/spv.merge-unreachable.frag.out b/Test/baseResults/spv.merge-unreachable.frag.out new file mode 100644 index 0000000..6542976 --- /dev/null +++ b/Test/baseResults/spv.merge-unreachable.frag.out @@ -0,0 +1,47 @@ +spv.merge-unreachable.frag +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + + +Linked fragment stage: + + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 25 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 9 + ExecutionMode 4 OriginLowerLeft + Source GLSL 450 + Name 4 "main" + Name 9 "v" + Decorate 9(v) Location 1 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypePointer Input 7(fvec4) + 9(v): 8(ptr) Variable Input + 11: 6(float) Constant 1036831949 + 12: 6(float) Constant 1045220557 + 13: 6(float) Constant 1050253722 + 14: 6(float) Constant 1053609165 + 15: 7(fvec4) ConstantComposite 11 12 13 14 + 16: TypeBool + 17: TypeVector 16(bool) 4 + 4(main): 2 Function None 3 + 5: Label + 10: 7(fvec4) Load 9(v) + 18: 17(bvec4) FOrdEqual 10 15 + 19: 16(bool) All 18 + SelectionMerge 21 None + BranchConditional 19 20 23 + 20: Label + Kill + 23: Label + Return + 21: Label + Return + FunctionEnd diff --git a/Test/baseResults/spv.switch.frag.out b/Test/baseResults/spv.switch.frag.out index 0d43083..918c1d6 100755 --- a/Test/baseResults/spv.switch.frag.out +++ b/Test/baseResults/spv.switch.frag.out @@ -106,6 +106,11 @@ Linked fragment stage: Switch 65 68 case 1: 66 case 2: 67 + 68: Label + 80: 6(float) Load 73(x) + 81: 6(float) ExtInst 1(GLSL.std.450) 15(Tan) 80 + Store 71(f) 81 + Branch 69 66: Label 74: 6(float) Load 73(x) 75: 6(float) ExtInst 1(GLSL.std.450) 13(Sin) 74 @@ -116,17 +121,19 @@ Linked fragment stage: 78: 6(float) ExtInst 1(GLSL.std.450) 14(Cos) 77 Store 71(f) 78 Branch 69 - 68: Label - 80: 6(float) Load 73(x) - 81: 6(float) ExtInst 1(GLSL.std.450) 15(Tan) 80 - Store 71(f) 81 - Branch 69 69: Label 83: 9(int) Load 60(c) SelectionMerge 87 None Switch 83 86 case 1: 84 case 2: 85 + 86: Label + 97: 6(float) Load 73(x) + 98: 6(float) ExtInst 1(GLSL.std.450) 15(Tan) 97 + 99: 6(float) Load 71(f) + 100: 6(float) FAdd 99 98 + Store 71(f) 100 + Branch 87 84: Label 88: 6(float) Load 73(x) 89: 6(float) ExtInst 1(GLSL.std.450) 13(Sin) 88 @@ -141,13 +148,6 @@ Linked fragment stage: 95: 6(float) FAdd 94 93 Store 71(f) 95 Branch 87 - 86: Label - 97: 6(float) Load 73(x) - 98: 6(float) ExtInst 1(GLSL.std.450) 15(Tan) 97 - 99: 6(float) Load 71(f) - 100: 6(float) FAdd 99 98 - Store 71(f) 100 - Branch 87 87: Label 102: 9(int) Load 60(c) SelectionMerge 105 None @@ -174,6 +174,13 @@ Linked fragment stage: Switch 117 120 case 1: 118 case 2: 119 + 120: Label + 148: 6(float) Load 73(x) + 149: 6(float) ExtInst 1(GLSL.std.450) 15(Tan) 148 + 150: 6(float) Load 71(f) + 151: 6(float) FAdd 150 149 + Store 71(f) 151 + Branch 121 118: Label 122: 6(float) Load 73(x) 123: 6(float) ExtInst 1(GLSL.std.450) 13(Sin) 122 @@ -207,13 +214,6 @@ Linked fragment stage: Branch 131 131: Label Branch 121 - 120: Label - 148: 6(float) Load 73(x) - 149: 6(float) ExtInst 1(GLSL.std.450) 15(Tan) 148 - 150: 6(float) Load 71(f) - 151: 6(float) FAdd 150 149 - Store 71(f) 151 - Branch 121 121: Label Store 153(i) 154 Branch 155 @@ -228,6 +228,13 @@ Linked fragment stage: Switch 162 165 case 1: 163 case 2: 164 + 165: Label + 196: 6(float) Load 73(x) + 197: 6(float) ExtInst 1(GLSL.std.450) 15(Tan) 196 + 198: 6(float) Load 71(f) + 199: 6(float) FAdd 198 197 + Store 71(f) 199 + Branch 166 163: Label 167: 6(float) Load 73(x) 168: 6(float) ExtInst 1(GLSL.std.450) 13(Sin) 167 @@ -265,13 +272,6 @@ Linked fragment stage: 193: 6(float) FAdd 192 191 Store 71(f) 193 Branch 166 - 165: Label - 196: 6(float) Load 73(x) - 197: 6(float) ExtInst 1(GLSL.std.450) 15(Tan) 196 - 198: 6(float) Load 71(f) - 199: 6(float) FAdd 198 197 - Store 71(f) 199 - Branch 166 166: Label 201: 6(float) Load 71(f) 203: 160(bool) FOrdLessThan 201 202 @@ -331,10 +331,10 @@ Linked fragment stage: SelectionMerge 254 None Switch 251 253 case 0: 252 - 252: Label - Branch 254 253: Label Branch 254 + 252: Label + Branch 254 254: Label 258: 9(int) Load 60(c) SelectionMerge 260 None diff --git a/Test/baseResults/spv.while-continue-break.vert.out b/Test/baseResults/spv.while-continue-break.vert.out old mode 100755 new mode 100644 index 5d6094f..b2ccbaa --- a/Test/baseResults/spv.while-continue-break.vert.out +++ b/Test/baseResults/spv.while-continue-break.vert.out @@ -60,9 +60,6 @@ Linked vertex stage: 23: Label Store 25(B) 20 Branch 10 - 26: Label - Store 27(C) 20 - Branch 24 24: Label 28: 6(int) Load 8(i) 30: 6(int) SMod 28 29 @@ -72,9 +69,6 @@ Linked vertex stage: 32: Label Store 25(B) 20 Branch 11 - 34: Label - Store 27(C) 20 - Branch 33 33: Label 35: 6(int) Load 8(i) 36: 6(int) IAdd 35 18 diff --git a/Test/spv.merge-unreachable.frag b/Test/spv.merge-unreachable.frag new file mode 100644 index 0000000..12f57cd --- /dev/null +++ b/Test/spv.merge-unreachable.frag @@ -0,0 +1,7 @@ +#version 450 +layout(location=1) in highp vec4 v; +void main (void) +{ + if (v == vec4(0.1,0.2,0.3,0.4)) discard; + else return; +} diff --git a/Test/test-spirv-list b/Test/test-spirv-list index 13ff7c0..d066124 100644 --- a/Test/test-spirv-list +++ b/Test/test-spirv-list @@ -57,6 +57,7 @@ spv.loopsArtificial.frag spv.matFun.vert spv.matrix.frag spv.matrix2.frag +spv.merge-unreachable.frag spv.newTexture.frag spv.nonSquare.vert spv.Operations.frag